import 'dart:collection';
import 'dart:io';
import 'dart:typed_data';
import 'dart:math';

import 'ip_utils_options.dart';
import 'ip_utils_errors.dart';

class IpUtils {
  // ==========================================================================
  // ====================== IPv4 constants ====================================
  // ==========================================================================

  /// ### English
  /// IPv4 address binary length (32 bits).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址二进制长度（32位）。
  static const int ipv4BinaryLength = 32;

  /// ### English
  /// IPv4 address decimal min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址十进制最小值 (0)。
  static const int ipv4MinInt = 0;

  /// ### English
  /// IPv4 address decimal max value.
  /// Value is 2^32 - 1 = 4294967295
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址十进制最大值。
  /// 值是 2^32 - 1 = 4294967295
  static const int ipv4MaxInt = 4294967295;

  /// ### English
  /// IPv4 address string min value ('0.0.0.0').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址字符串最小值 ('0.0.0.0')。
  static const String ipv4MinString = '0.0.0.0';

  /// ### English
  /// IPv4 address string max value ('255.255.255.255').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址字符串最大值 ('255.255.255.255')。
  static const String ipv4MaxString = '255.255.255.255';

  /// ### English
  /// IPv4 address string min length. e.g. "1.1.1.1".length == 7
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址字符串最小长度。例如, "1.1.1.1".length == 7
  static const int ipv4MinStringLength = 7;

  /// ### English
  /// IPv4 address string max length. e.g. "255.255.255.255".length == 15
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址字符串最大长度。例如, "255.255.255.255".length == 15
  static const int ipv4MaxStringLength = 15;

  /// ### English
  /// IPv4 address has 4 segments. e.g. "255.255.255.255" has 4 segments.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址有4段。例如, "255.255.255.255"有4段。
  static const int ipv4SegmentCount = 4;

  /// ### English
  /// IPv4 address every segment decimal min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的十进制最小值 (0)。
  static const int ipv4SegmentMinInt = 0;

  /// ### English
  /// IPv4 address every segment decimal max value (255).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每个部分的十进制最大值 (255)。
  static const int ipv4SegmentMaxInt = 255;

  /// ### English
  /// IPv4 address every segment decimal min value string representation ('0').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的十进制最小值字符串表示 ('0')。
  static const String ipv4SegmentMinString = '0';

  /// ### English
  /// IPv4 address every segment decimal max value string representation ('255').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的十进制最大值字符串表示 ('255')。
  static const String ipv4SegmentMaxString = '255';

  /// ### English
  ///IPv4 address every segment min length (1).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的最小长度 (1)。
  static const int ipv4SegmentMinLength = 1;

  /// ### English
  ///IPv4 address every segment max length (3).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的最大长度 (3)。
  static const int ipv4SegmentMaxLength = 3;

  /// ### English
  /// IPv4 address CIDR min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址CIDR最小值 (0)。
  static const int ipv4CidrMin = 0;

  /// ### English
  /// IPv4 address CIDR max value (32).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址CIDR最大值 (32)。
  static const int ipv4CidrMax = 32;

  /// ### English
  /// IPv4 loopback address ('127.0.0.1').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4环回地址 ('127.0.0.1')。
  static const String ipv4Loopback = '127.0.0.1';

  /// ### English
  /// IPv4 any address ('0.0.0.0').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4任意地址 ('0.0.0.0')。
  static const String ipv4Any = '0.0.0.0';

  /// ### English
  /// IPv4 mask:cidr pairs.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4 掩码:CIDR 对。
  static final Map<String, int> ipv4MaskCidrMap = Map.unmodifiable({
    "255.255.255.255": 32,
    "255.255.255.254": 31,
    "255.255.255.252": 30,
    "255.255.255.248": 29,
    "255.255.255.240": 28,
    "255.255.255.224": 27,
    "255.255.255.192": 26,
    "255.255.255.128": 25,
    "255.255.255.0": 24,
    "255.255.254.0": 23,
    "255.255.252.0": 22,
    "255.255.248.0": 21,
    "255.255.240.0": 20,
    "255.255.224.0": 19,
    "255.255.192.0": 18,
    "255.255.128.0": 17,
    "255.255.0.0": 16,
    "255.254.0.0": 15,
    "255.252.0.0": 14,
    "255.248.0.0": 13,
    "255.240.0.0": 12,
    "255.224.0.0": 11,
    "255.192.0.0": 10,
    "255.128.0.0": 9,
    "255.0.0.0": 8,
    "254.0.0.0": 7,
    "252.0.0.0": 6,
    "248.0.0.0": 5,
    "240.0.0.0": 4,
    "224.0.0.0": 3,
    "192.0.0.0": 2,
    "128.0.0.0": 1,
    "0.0.0.0": 0,
  });

  // === IPv4 regular expressions ====

  /// ### English
  /// The leading zero mode of each segment of the IPV4 address is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址每段的前导零模式与对应的正则表达式对。
  static final Map<LeadingZerosMode, RegExp>
      ipv4SegmentLeadingZerosModeAndRegExpMap = UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(r'^(\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5]))$'),
    LeadingZerosMode.included:
        RegExp(r'^(0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$'),
    LeadingZerosMode.includedCompletely:
        RegExp(r'^(00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$'),
    LeadingZerosMode.excluded:
        RegExp(r'^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$'),
  });

  /// ### English
  /// The leading zero mode of the PV4 address is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4地址的前导零模式与对应的正则表达式对。
  static final Map<LeadingZerosMode, RegExp> ipv4LeadingZerosModeAndRegExpMap =
      UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(
        r'^(((\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5]))\.){3}(\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5])))$'),
    LeadingZerosMode.included: RegExp(
        r'^(((0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}(0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
    LeadingZerosMode.includedCompletely: RegExp(
        r'^(((00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}(00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
    LeadingZerosMode.excluded: RegExp(
        r'^(((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  });

  /// ### English
  /// The leading zero mode of the IPv4 CIDR is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv4 CIDR 的前导零模式与对应的正则表达式对。
  static final Map<LeadingZerosMode, RegExp>
      ipv4CidrLeadingZerosModeAndRegExpMap = UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(r'^(0?\d|[12]\d|3[0-2])$'),
    LeadingZerosMode.included: RegExp(r'^(0\d|[12]\d|3[0-2])$'),
    LeadingZerosMode.includedCompletely: RegExp(r'^(0\d|[12]\d|3[0-2])$'),
    LeadingZerosMode.excluded: RegExp(r'^(\d|[12]\d|3[0-2])$'),
  });

  // ==========================================================================
  // ====================== IPv6 constants ====================================
  // ==========================================================================

  /// ### English
  /// IPv6 address binary length (128 bits).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址二进制长度（128位）。
  static const int ipv6BinaryLength = 128;

  /// ### English
  /// IPv6 address decimal min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址十进制最小值 (0)。
  static final BigInt ipv6MinBigInt = BigInt.zero;

  /// ### English
  /// IPv6 address decimal max value.
  /// Value is 2^128 - 1 = 340282366920938463463374607431768211455
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址十进制最大值。
  /// 值是 2^128 - 1 = 340282366920938463463374607431768211455
  static final BigInt ipv6MaxBigInt =
      BigInt.parse('340282366920938463463374607431768211455');

  /// ### English
  /// IPv6 address string min value ('::').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址字符串最小值 ('::')。
  static const String ipv6MinString = '::';

  /// ### English
  /// IPv6 address string max value ('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址字符串最大值 ('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')。
  static const String ipv6MaxString = 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff';

  /// ### English
  /// IPv6 address string min length. "::".length == 2
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址字符串最小长度。 "::".length == 2
  static const int ipv6MinStringLength = 2;

  /// ### English
  /// IPv6 address string max length.
  /// Example: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".length == 39
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址字符串最大长度。
  /// 例如: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".length == 39
  static const int ipv6MaxStringLength = 39;

  /// ### English
  /// IPv6 address every segment min length.
  /// Example: "0".length == 1
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的最小长度。例如: "f".length == 1
  static const int ipv6SegmentMinLength = 1;

  /// ### English
  /// IPv6 address every segment max length.
  /// Example: "16ff".length == 4
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的最大长度。例如: "16ff".length == 4
  static const int ipv6SegmentMaxLength = 4;

  /// ### English
  /// IPv6 address every segment decimal min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的十进制最小值 (0)。
  static const int ipv6SegmentMinInt = 0;

  /// ### English
  /// IPv4 address every segment decimal max value (65535).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的十进制最大值 (65535)。
  static const int ipv6SegmentMaxInt = 0xffff;

  /// ### English
  /// IPv6 address every segment min value string representation ('0').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的最小值字符串表示 ('0')。
  static const String ipv6SegmentMinString = '0';

  /// ### English
  /// IPv6 address every segment max value string representation ('ffff').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址每段的最大值字符串表示 ('ffff')。
  static const String ipv6SegmentMaxString = 'ffff';

  /// ### English
  /// IPv6 address has min 3 segments.
  /// '::'.split(':').length == 3
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址至少有3段。
  /// '::'.split(':').length == 3
  static const int ipv6MinSegmentCount = 3;

  /// ### English
  /// IPv6 address has max 8 segments.
  /// "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".split(':').length == 8
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址最多有8段。
  /// "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".split(':').length == 8
  static const int ipv6MaxSegmentCount = 8;

  /// ### English
  /// IPv6 address CIDR min value (0).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址CIDR最小值 (0)。
  static const int ipv6CidrMin = 0;

  /// ### English
  /// IPv6 address CIDR max value (128).
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址CIDR最大值 (128)。
  static const int ipv6CidrMax = 128;

  /// ### English
  /// IPv6 loopback address ('::1').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6环回地址 ('::1')。
  static const String ipv6Loopback = '::1';

  /// ### English
  /// IPv6 any address ('::').
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6任意地址 ('::')。
  static const String ipv6Any = '::';

  // === IPv6 regular expressions ====

  /// ### English
  /// The leading zero mode of each segment of the IPV6 address is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址段的前导零模式与对应的正则表达式对。
  static final ipv6SegmentLeadingZerosModeAndRegExpMap = UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(r'^([0-9a-f]{1,4})$'),
    LeadingZerosMode.included: RegExp(
        r'^(0{1,3}[0-9a-f]|0{1,2}[0-9a-f]{2}|0[0-9a-f]{1,3}|[1-9a-f][0-9a-f]{1,3})$'),
    LeadingZerosMode.includedCompletely: RegExp(
        r'^(0{3}[0-9a-f]|0{2}[0-9a-f]{2}|0[0-9a-f]{3}|[1-9a-f][0-9a-f]{1,3})$'),
    LeadingZerosMode.excluded: RegExp(r'^([1-9a-f][0-9a-f]{1,3}|[0-9a-f])$'),
  });

  /// ### English
  /// The leading zero mode of the IPV6 address is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6地址的前导零模式与对应的正则表达式对。
  static final ipv6NormalLeadingZerosModeAndRegExpMap = UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(r'^(([0-9a-f]{1,4}:){7}[0-9a-f]{1,4})$'),
    LeadingZerosMode.included: RegExp(
        r'^(((0{1,3}[0-9a-f]|0{1,2}[0-9a-f]{2}|0[0-9a-f]{1,3}|[1-9a-f][0-9a-f]{1,3}):){7}'
        r'(0{1,3}[0-9a-f]|0{1,2}[0-9a-f]{2}|0[0-9a-f]{1,3}|[1-9a-f][0-9a-f]{1,3}))$'),
    LeadingZerosMode.includedCompletely: RegExp(
        r'^(((0{3}[0-9a-f]|0{2}[0-9a-f]{2}|0[0-9a-f]{3}|[1-9a-f][0-9a-f]{1,3}):){7}'
        r'(0{3}[0-9a-f]|0{2}[0-9a-f]{2}|0[0-9a-f]{3}|[1-9a-f][0-9a-f]{1,3}))$'),
    LeadingZerosMode.excluded: RegExp(
        r'^((([1-9a-f][0-9a-f]{1,3}|[0-9a-f]):){7}([1-9a-f][0-9a-f]{1,3}|[0-9a-f]))$'),
  });

  static RegExp _createIpv4MappedIpv6RegExp(String str, LeadingZerosMode mode) {
    var regExp = ipv4LeadingZerosModeAndRegExpMap[mode];
    var regExpStr =
        regExp?.pattern.replaceFirst('^(', '').replaceFirst(')\$', '');
    return RegExp(r'^(' + str + regExpStr! + r')$');
  }

  static final ipv4MappedIpv6NormalLeadingZerosModeAndRegExpMap =
      UnmodifiableMapView({
    LeadingZerosMode.any:
        _createIpv4MappedIpv6RegExp('(0{1,4}:){5}ffff:', LeadingZerosMode.any),
    LeadingZerosMode.included: _createIpv4MappedIpv6RegExp(
        '(0{2,4}:){5}ffff:', LeadingZerosMode.included),
    LeadingZerosMode.includedCompletely: _createIpv4MappedIpv6RegExp(
        '(0{4}:){5}ffff:', LeadingZerosMode.includedCompletely),
    LeadingZerosMode.excluded:
        _createIpv4MappedIpv6RegExp('(0:){5}ffff:', LeadingZerosMode.excluded),
  });

  // static final ipv4MappedIpv6NormalLeadingZerosModeAndRegExpMap =
  //     UnmodifiableMapView({
  //   LeadingZerosMode.any:
  //       RegExp(r'^((0{1,4}:){5}ffff:((\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.included: RegExp(
  //       r'^((0{2,4}:){5}ffff:((0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //       r'(0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.includedCompletely: RegExp(
  //       r'^((0{4}:){5}ffff:((00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //       r'(00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.excluded:
  //       RegExp(r'^((0:){5}ffff:((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  // });
  static final ipv4MappedIpv6CompressedLeadingZerosModeAndRegExpMap =
      UnmodifiableMapView({
    LeadingZerosMode.any:
        _createIpv4MappedIpv6RegExp('::ffff:', LeadingZerosMode.any),
    LeadingZerosMode.included:
        _createIpv4MappedIpv6RegExp('::ffff:', LeadingZerosMode.included),
    LeadingZerosMode.includedCompletely: _createIpv4MappedIpv6RegExp(
        '::ffff:', LeadingZerosMode.includedCompletely),
    LeadingZerosMode.excluded:
        _createIpv4MappedIpv6RegExp('::ffff:', LeadingZerosMode.excluded),
  });

  // static final ipv4MappedIpv6CompressedLeadingZerosModeAndRegExpMap =
  //     UnmodifiableMapView({
  //   LeadingZerosMode.any:
  //       RegExp(r'^(::ffff:((\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(\d|\d\d|[01]\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.included:
  //       RegExp(r'^(::ffff:((0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(0{1,2}\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.includedCompletely:
  //       RegExp(r'^(::ffff:((00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(00\d|0[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  //   LeadingZerosMode.excluded:
  //       RegExp(r'^(::ffff:((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){3}'
  //           r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5])))$'),
  // });

  /// ### English
  /// The leading zero mode of the IPv6 CIDR is paired
  /// with the corresponding regular expression.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// IPv6 CIDR 的前导零模式与对应的正则表达式对。
  static final Map<LeadingZerosMode, RegExp>
      ipv6CidrLeadingZerosModeAndRegExpMap = UnmodifiableMapView({
    LeadingZerosMode.any: RegExp(r'^(0{0,2}\d|0?\d\d|1[0-2][0-8])$'),
    LeadingZerosMode.included: RegExp(r'^(0{1,2}\d|0\d\d|1[0-2][0-8])$'),
    LeadingZerosMode.includedCompletely:
        RegExp(r'^(0{2}\d|0\d\d|1[0-2][0-8])$'),
    LeadingZerosMode.excluded: RegExp(r'^(\d|[1-9]\d|1[0-2][0-8])$'),
  });

  // ==========================================================================
  // ====================== Other constants ===================================
  // ==========================================================================

  /// Leading zeros regular expression.
  static final leadingZerosRegExp = RegExp(r'^0+\w+');

  // ==========================================================================
  // ====================== Constructors ======================================
  // ==========================================================================

  late IpUtilsOptions options;

  IpUtils([IpUtilsOptions? options]) {
    options == null
        ? this.options = IpUtilsOptions.rfc5952()
        : this.options = options;
  }

  // ==========================================================================
  // ====================== IPv4 functions ====================================
  // ==========================================================================

  /// ### English
  /// Create a list of IPv4 addresses in the given [ipRanges].
  ///
  /// [ipRanges] can be a single IP address or a range of IP addresses
  /// in the format of "start-end".
  /// Multiple IP ranges can be separated by comma.
  ///
  /// For example:
  ///   - "192.168.1.1-192.168.1.10"
  ///   - "192.168.1.1-10"    Equivalent to "192.168.1.1-192.168.1.10"
  ///   - "192.168.1.1-192.168.1.1"  Equivalent to "192.168.1.1"
  ///   - "192.168.1.1-2.1"  Equivalent to "192.168.1.1-192.168.2.1"
  ///   - "192.168.1.1"
  ///   - "192.168.1.0-10,192.168.2.0-100"
  ///
  /// Throws an [IpError] if the given [ipRanges] is invalid.
  /// Throws an [IpRangeError] if the given [ipRanges] has invalid range or
  /// start IP address is greater than end IP address in the range.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 根据给定的[ipRanges]创建IPv4地址列表。
  ///
  /// [ipRanges]可以是一个IPv4地址或一个IPv4地址范围，格式为"start-end"。
  /// 多个IP范围可以用逗号分隔。
  ///
  /// 例如:
  ///   - "192.168.1.1-192.168.1.10"
  ///   - "192.168.1.1-10"    等价于 "192.168.1.1-192.168.1.10"
  ///   - "192.168.1.1-192.168.1.1"  等价于 "192.168.1.1"
  ///   - "192.168.1.1-2.1"  等价于 "192.168.1.1-192.168.2.1"
  ///   - "192.168.1.1"
  ///   - "192.168.1.0-10,192.168.2.0-100"
  ///
  /// 如果[ipRanges]格式不正确，会抛出[IpError]。
  /// 如果[ipRanges]中存在无效的IP范围或起始IP地址大于结束IP地址，会抛出[IpRangeError]。
  List<String> createIpv4ListFromRanges(String ipRanges,
      {LeadingZerosMode? inputMode, LeadingZerosMode? outputMode}) {
    handleRange(
        String startIp, String endIpOld, String ipRange, List<String> ipList) {
      if (isNotIpv4(startIp, inputMode: inputMode)) {
        throw IpError('Invalid start IP: $startIp in range $ipRange');
      }
      String endIp = completeEndIpv4(startIp, endIpOld,
          inputMode: inputMode, outputMode: outputMode);

      int startInt = ipv4ToInt(startIp, inputMode: inputMode);
      int endInt = ipv4ToInt(endIp, inputMode: inputMode);
      if (startInt > endInt) {
        throw IpRangeError(
            'Invalid IP range: $ipRange, start IP $startIp is greater than end IP $endIpOld');
      }
      for (int i = startInt; i <= endInt; i++) {
        ipList.add(intToIpv4(i, outputMode: outputMode));
      }
    }

    return _createIpListFromRanges(ipRanges, handleRange);
  }

  /// ### English
  /// Generate a list of IPv4 addresses in the given [count].
  ///
  /// [count] must be greater than zero.
  /// If [count] is less than 1, returns an empty list.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 生成 [count] 个随机 IPv4 地址。
  ///
  /// [count] 必须大于零。
  /// 如果 [count] 小于 1，返回一个空列表。
  List<String> generateRandomIpv4List(int count,
      {LeadingZerosMode? outputMode}) {
    List<String> ipList = [];
    final random = Random();
    int ipv4Int = 0;

    for (int i = 0; i < count; i++) {
      ipv4Int = random.nextInt(ipv4MaxInt + 1);
      ipList.add(intToIpv4(ipv4Int, outputMode: outputMode));
    }
    return ipList;
  }

  /// ### English
  /// Generate a random IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 生成一个随机的 IPv4 地址。
  String generateRandomIpv4({LeadingZerosMode? outputMode}) {
    final random = Random();
    int ipv4Int = random.nextInt(ipv4MaxInt + 1);
    return intToIpv4(ipv4Int, outputMode: outputMode);
  }

  /// ### English
  /// Handles the leading zeros of [ip] according to [outputMode].
  ///
  /// [inputMode] defaults to LeadingZerosMode.any, not [options.ipv4InputAddressLeadingZerosMode].
  /// [outputMode] defaults to [options.ipv4OutputAddressLeadingZerosMode].
  ///
  /// When [outputMode] is
  /// - LeadingZerosMode.any, returns [ip] as is.
  /// - LeadingZerosMode.included, returns [ip] with incomplete leading zeros added.
  /// - LeadingZerosMode.includedCompletely, returns [ip] with complete leading zeros added.
  /// - LeadingZerosMode.excluded, returns [ip] with leading zeros removed.
  ///
  /// Examples:
  /// ``` dart
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.any); // returns '192.168.0.1'
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.included); // returns '192.168.00.01'
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.includedCompletely); // returns '192.168.000.001'
  /// handleIpv4Output('192.168.00.001', outputMode: LeadingZerosMode.excluded); // returns '192.168.0.1'
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 根据[outputMode]处理[ip]的前导零。
  ///
  /// [inputMode] 输入模式，默认为 `LeadingZerosMode.any`, 而不是[options.ipv4InputAddressLeadingZerosMode]。
  /// [outputMode] 输出模式，默认为 [options.ipv4OutputAddressLeadingZerosMode]。
  ///
  /// 当 [outputMode] 的值为:
  /// - LeadingZerosMode.any, 直接返回 [ip].
  /// - LeadingZerosMode.included, 为[ip]添加不完整的前导零,并返回[ip].
  /// - LeadingZerosMode.includedCompletely, 为[ip]添加完整的前导零,并返回[ip].
  /// - LeadingZerosMode.excluded, 删除[ip]的前导零,并返回[ip].
  ///
  /// Examples:
  /// ``` dart
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.any); // returns '192.168.0.1'
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.included); // returns '192.168.00.01'
  /// handleIpv4Output('192.168.0.1', outputMode: LeadingZerosMode.includedCompletely); // returns '192.168.000.001'
  /// handleIpv4Output('192.168.00.001', outputMode: LeadingZerosMode.excluded); // returns '192.168.0.1'
  /// ```
  String handleIpv4Output(String ip,
      {LeadingZerosMode inputMode = LeadingZerosMode.any,
      LeadingZerosMode? outputMode}) {
    outputMode ??= options.ipv4OutputAddressLeadingZerosMode;

    switch (outputMode) {
      case LeadingZerosMode.any:
        return ip;
      case LeadingZerosMode.included:
        return addIpv4LeadingZeros(ip,
            inputMode: inputMode, incompleteLeadingZeros: true);
      case LeadingZerosMode.includedCompletely:
        return addIpv4LeadingZeros(ip,
            inputMode: inputMode, incompleteLeadingZeros: false);
      case LeadingZerosMode.excluded:
        return removeIpv4LeadingZeros(ip, inputMode: inputMode);
    }
  }

  /// ### English
  /// Compares two IPv4 addresses.
  ///
  /// Same as [compareIpv4Default] but throws an [IpError] if the given [left] or [right] is invalid IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 比较两个 IPv4 地址。
  ///
  /// 此方法与[compareIpv4Default]类似, 但当[left]或[right]不是有效的IPv4地址时,会抛出[IpError]。
  int compareIpv4(String left, String right, {LeadingZerosMode? inputMode}) {
    return ipv4ToInt(left, inputMode: inputMode)
        .compareTo(ipv4ToInt(right, inputMode: inputMode));
  }

  /// ### English
  /// Compares two IPv4 addresses.
  ///
  /// - Returns a negative integer, if [left] less than [right].
  /// - Returns zero, if [left] is equal to [right].
  /// - Returns a positive integer, if [left] greater than [right].
  ///
  /// Throws an [IpError] if the given [left] or [right] is invalid IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 比较两个 IPv4 地址。
  ///
  /// - 返回一个负整数，如果 [left] 小于 [right]。
  /// - 返回零，如果 [left] 等于 [right]。
  /// - 返回一个正整数，如果 [left] 大于 [right]。
  ///
  /// 如果给定的 [left] 或 [right] 不是有效的 IPv4 地址，则返回[defaultValue]。
  int? compareIpv4Default(String left, String right,
      {int? defaultValue, LeadingZerosMode? inputMode}) {
    try {
      return ipv4ToInt(left, inputMode: inputMode)
          .compareTo(ipv4ToInt(right, inputMode: inputMode));
    } on IpError {
      return defaultValue;
    }
  }

  /// ### English
  /// To complete the [endIp] based on the [startIp].
  ///
  /// Same as [completeEndIpv4Default] but throws an [IpError] if the given [startIp] or [endIp] is invalid.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 根据 [startIp] 补全 [endIp]。
  ///
  /// 这个方法与 [completeEndIpv4Default] 相同，只是当 [startIp] 或 [endIp] 无效时会抛出 [IpError]。
  String completeEndIpv4(String startIp, String endIp,
      {LeadingZerosMode? inputMode, LeadingZerosMode? outputMode}) {
    if (isNotIpv4(startIp, inputMode: inputMode)) {
      throw IpError('Invalid start IP: $startIp');
    }

    inputMode ??= options.ipv4InputAddressLeadingZerosMode;
    outputMode ??= options.ipv4OutputAddressLeadingZerosMode;

    List<String> startIpParts = startIp.split('.');
    List<String> endIpParts = endIp.split('.');
    int endIpPartsLength = endIpParts.length;
    if (endIpPartsLength > ipv4SegmentCount ||
        isNotIpv4Segments(endIpParts,
            inputMode: inputMode, checkLength: false)) {
      throw IpError('Invalid end IP: $endIp');
    }
    // completion to [endIp] if it is a partial IP address
    for (int i = 0; i < ipv4SegmentCount - endIpPartsLength; i++) {
      endIpParts.insert(i, startIpParts[i]);
    }

    endIp = endIpParts.join('.');
    return handleIpv4Output(endIp, outputMode: outputMode);
  }

  /// ### English
  /// To complete the [endIp] based on the [startIp].
  ///
  /// Returns [defaultValue] if the given [startIp] is invalid or [endIp] is invalid.
  /// [defaultValue] is `null` by default.
  ///
  /// Examples:
  /// ``` dart
  /// // Use options.ipv4InputIpLeadingZerosMode to inputMode.
  /// // And use options.ipv4OutputIpLeadingZerosMode to outputMode.
  /// completeEndIpv4Default('192.168.0.1', '10'); // returns '192.168.0.10'
  ///
  /// // returns '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // returns '192.168.00.10'
  /// completeEndIpv4Default('192.168.00.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // returns '192.168.000.10'
  /// completeEndIpv4Default('192.168.000.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // returns '192.168.00.010'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.included);
  ///
  /// // returns '192.168.000.010'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.includedCompletely);
  ///
  /// // returns '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.excluded);
  ///
  /// // returns null
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.included,
  ///        outputMode: LeadingZerosMode.excluded);
  ///
  /// // returns ''
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.includedCompletely,
  ///        outputMode: LeadingZerosMode.excluded,
  ///        defaultValue: '');
  ///
  /// // returns '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.excluded,
  ///        outputMode: LeadingZerosMode.excluded,
  ///        defaultValue: '');
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 根据[startIp]补全[endIp]。
  ///
  /// 如果[startIp]或[endIp]无效, 返回[defaultValue], 默认值为`null`。
  ///
  /// [inputMode]用于确定IPv4地址的前导零的输入格式。如果[inputMode]为`null`,
  /// 则使用[options.ipv4InputAddressLeadingZerosMode]的值。
  ///
  /// [outputMode]用于确定IPv4地址的前导零的输出格式。如果[outputMode]为`null`,
  /// 则使用[options.ipv4OutputAddressLeadingZerosMode]的值。
  ///
  /// 示例
  /// ```dart
  /// // 使用options.ipv4InputIpLeadingZerosMode作为inputMode。
  /// // 使用options.ipv4OutputIpLeadingZerosMode作为outputMode。
  /// completeEndIpv4Default('192.168.0.1', '10'); // 返回 '192.168.0.10'
  ///
  /// // 返回 '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // 返回 '192.168.00.10'
  /// completeEndIpv4Default('192.168.00.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // 返回 '192.168.000.10'
  /// completeEndIpv4Default('192.168.000.1', '10',
  ///        inputMode: LeadingZerosMode.any, outputMode: LeadingZerosMode.any);
  ///
  /// // 返回 '192.168.00.010'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.included);
  ///
  /// // 返回 '192.168.000.010'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.includedCompletely);
  ///
  /// // 返回 '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.any,
  ///        outputMode: LeadingZerosMode.excluded);
  ///
  /// // 返回 null
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.included,
  ///        outputMode: LeadingZerosMode.excluded);
  ///
  /// // 返回 ''
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.includedCompletely,
  ///        outputMode: LeadingZerosMode.excluded,
  ///        defaultValue: '');
  ///
  /// // 返回 '192.168.0.10'
  /// completeEndIpv4Default('192.168.0.1', '10',
  ///        inputMode: LeadingZerosMode.excluded,
  ///        outputMode: LeadingZerosMode.excluded,
  ///        defaultValue: '');
  /// ```
  String? completeEndIpv4Default(String startIp, String endIp,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      LeadingZerosMode? outputMode}) {
    try {
      return completeEndIpv4(startIp, endIp,
          inputMode: inputMode, outputMode: outputMode);
    } on IpError {
      return defaultValue;
    }
  }

  /// ### English
  /// Convert the given ipv4 String [ipv4] to an decimal integer.
  ///
  /// Same as [ipv4ToIntDefault] but throws an [IpError] if the given [ipv4] is not a valid IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的IPv4字符串[ipv4]转换为十进制整数。
  ///
  /// 与[ipv4ToIntDefault]相同, 但如果[ipv4]不是有效的IPv4地址, 则会抛出[IpError]异常。
  int ipv4ToInt(String ipv4, {LeadingZerosMode? inputMode}) {
    int? ipv4Int = ipv4ToIntDefault(ipv4, inputMode: inputMode);
    if (ipv4Int != null) {
      return ipv4Int;
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  /// ### English
  /// Convert the given ipv4 String [ipv4] to an decimal integer.
  ///
  /// Returns [defaultValue] if the given [ipv4] is not a valid IPv4 address.
  /// [defaultValue] is `null` by default.
  ///
  /// [inputMode] is used to determine the input format of the IPv4 address leading zeros.
  /// If [inputMode] is `null`, the value of [options.ipv4InputAddressLeadingZerosMode] is used.
  ///
  /// Example
  /// ```dart
  /// ipv4ToIntDefault('192.168.1.1'); // inputMode is options.ipv4InputIpLeadingZerosMode
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.any); // returns 3232235777
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.excluded); // returns 3232235777
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.included); // returns null
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.includedCompletely, defaultValue: -1); // returns -1
  ///
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.any); // returns 3232235777
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.excluded); // returns null
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.included); // returns 3232235777
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.includedCompletely); // returns null
  ///
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.any); // returns 3232235777
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.excluded); // returns null
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.included); // returns 3232235777
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.includedCompletely); // returns 3232235777
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的IPv4字符串[ipv4]转换为十进制整数。
  ///
  /// 如果[ipv4]不是有效的IPv4地址, 返回[defaultValue], 默认值为`null`。
  ///
  /// [inputMode]用于确定IPv4地址的前导零的输入格式。如果[inputMode]为`null`,
  /// 则使用[options.ipv4InputAddressLeadingZerosMode]的值。
  ///
  /// 示例
  /// ```dart
  /// ipv4ToIntDefault('192.168.1.1'); // inputMode is options.ipv4InputIpLeadingZerosMode
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.any); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.excluded); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.included); // 返回 null
  /// ipv4ToIntDefault('192.168.1.1', inputMode: LeadingZerosMode.includedCompletely, defaultValue: -1); // 返回 -1
  ///
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.any); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.excluded); // 返回 null
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.included); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.01.01', inputMode: LeadingZerosMode.includedCompletely); // 返回 null
  ///
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.any); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.excluded); // 返回 null
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.included); // 返回 3232235777
  /// ipv4ToIntDefault('192.168.001.001', inputMode: LeadingZerosMode.includedCompletely); // 返回 3232235777
  /// ```
  int? ipv4ToIntDefault(String ipv4,
      {int? defaultValue, LeadingZerosMode? inputMode}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      List<int> parts = ipv4.split('.').map(int.parse).toList();
      return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
    }
    return defaultValue;
  }

  /// ### English
  /// Convert the given decimal integer [number] to an IPv4 String.
  ///
  /// BigInt version of [ipv4ToInt]
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的IPv4字符串[ipv4]转换为大整数。
  ///
  /// [ipv4ToInt]的BigInt版本。
  BigInt ipv4ToBigInt(String ipv4, {LeadingZerosMode? inputMode}) {
    return BigInt.from(ipv4ToInt(ipv4, inputMode: inputMode));
  }

  /// ### English
  /// Convert the given IPv4 String [ipv4] to a big integer.
  ///
  /// BigInt version of [ipv4ToIntDefault]
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的IPv4字符串[ipv4]转换为大整数。
  ///
  /// [ipv4ToIntDefault]的BigInt版本。
  BigInt? ipv4ToBigIntDefault(String ipv4,
      {BigInt? defaultValue, LeadingZerosMode? inputMode}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      return BigInt.from(ipv4ToInt(ipv4, inputMode: inputMode));
    }
    return defaultValue;
  }

  /// ### English
  /// Convert the given decimal integer [number] to an IPv4 String.
  ///
  /// Same as [intToIpv4],but throw an [IpRangeError] if the given [number]
  /// is not in the range of [ipv4MinInt] to [ipv4MaxInt].
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的十进制整数[number]转换为IPv4字符串。
  ///
  /// 与[intToIpv4]相同, 但如果[number]不在[ipv4MinInt]到[ipv4MaxInt]的范围内,
  /// 则抛出[IpRangeError]异常。
  String intToIpv4(int number, {LeadingZerosMode? outputMode}) {
    String? ipv4 = intToIpv4Default(number, outputMode: outputMode);
    if (ipv4 != null) {
      return ipv4;
    }
    throw IpRangeError.range(
        number,
        ipv4MinInt,
        ipv4MaxInt,
        'number',
        'The number must be in the range of '
            '$ipv4MinInt to $ipv4MaxInt');
  }

  /// ### English
  /// Convert the given decimal integer [number] to an IPv4 String.
  ///
  /// Returns [defaultValue] if the given [number] is not a valid IPv4 integer.
  /// [defaultValue] is `null` by default.
  ///
  /// [outputMode] is used to determine the output format of the IPv4 address leading zeros.
  /// If [outputMode] is `null`, the value of [options.ipv4OutputAddressLeadingZerosMode] is used.
  ///
  /// Example
  /// ```dart
  /// intToIpv4Default(-1); // returns null
  /// intToIpv4Default(0); //  outputMode is options.ipv4OutputIpLeadingZerosMode
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.any); // returns "0.0.0.0"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.excluded); // returns "0.0.0.0"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.included); // returns "00.00.00.00"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.includedCompletely); // returns "000.000.000.000"
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的十进制整数[number]转换为IPv4字符串。
  ///
  /// 如果[number]不是有效的IPv4整数, 返回[defaultValue], 默认值为`null`。
  ///
  /// [outputMode]用于确定IPv4地址的前导零的输出格式。如果[outputMode]为`null`,
  /// 则使用[options.ipv4OutputAddressLeadingZerosMode]的值。
  ///
  /// 示例
  /// ```dart
  /// intToIpv4Default(-1); // 返回 null
  /// intToIpv4Default(0); // 根据 options.ipv4OutputIpLeadingZerosMode 的值返回对应的ipv4地址
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.any); // 返回 "0.0.0.0"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.excluded); // 返回 "0.0.0.0"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.included); // 返回 "00.00.00.00"
  /// intToIpv4Default(0, outputMode: LeadingZerosMode.includedCompletely); // 返回 "000.000.000.000"
  /// ```
  String? intToIpv4Default(int number,
      {String? defaultValue, LeadingZerosMode? outputMode}) {
    if (isIpv4Int(number)) {
      String ipv4 = '${(number >> 24) & 0xFF}.'
          '${(number >> 16) & 0xFF}.'
          '${(number >> 8) & 0xFF}.'
          '${number & 0xFF}';
      return handleIpv4Output(ipv4,
          inputMode: LeadingZerosMode.any, outputMode: outputMode);
    }
    return defaultValue;
  }

  /// ### English
  /// Convert the given big integer [number] to an IPv4 String.
  ///
  /// BigInt version of [intToIpv4]
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的大整数[number]转换为IPv4字符串。
  ///
  /// [intToIpv4]的BigInt版本。
  String bigIntToIpv4(BigInt number, {LeadingZerosMode? outputMode}) {
    if (isIpv4BigInt(number)) {
      return intToIpv4(number.toInt(), outputMode: outputMode);
    }
    throw IpRangeError.range(
        number.toInt(),
        ipv4MinInt,
        ipv4MaxInt,
        'number',
        'The number must be in the range of '
            '$ipv4MinInt to $ipv4MaxInt');
  }

  /// ### English
  /// Convert the given big integer [number] to an IPv4 String.
  ///
  /// BigInt version of [intToIpv4Default]
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将给定的大整数[number]转换为IPv4字符串。
  ///
  /// [intToIpv4Default]的BigInt版本。
  String? bigIntToIpv4Default(BigInt number,
      {String? defaultValue, LeadingZerosMode? outputMode}) {
    if (isIpv4BigInt(number)) {
      return intToIpv4(number.toInt(), outputMode: outputMode);
    }
    return defaultValue;
  }

  /// ### English
  /// Checks if the given all elements of [segments] are valid IPv4 address part.
  ///
  /// [checkLength] whether check the length of [segments], default is `true`.
  /// If `true`, the length of [segments] must be 4.
  ///
  /// Example
  /// ```dart
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segments(["192", "168", "1", "1"]);
  /// // returns true
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.any);
  /// // returns false, Leading zeros must be included
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.included);
  /// // returns false, Leading zeros must be included completely
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.includedCompletely);
  /// // returns true, Leading zeros must be excluded
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.excluded);
  ///
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segments(["192", "168", "01", "01"]);
  /// // returns true
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.any);
  /// // returns true, Leading zeros must be included
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.included);
  /// // returns false, Leading zeros must be included completely
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.includedCompletely);
  /// // returns true, Leading zeros must be excluded
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.excluded);
  ///
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segments(["192", "168", "001", "001"]);
  /// // returns true
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.any);
  /// // returns true, Leading zeros must be included
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.included);
  /// // returns true, Leading zeros must be included completely
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.includedCompletely);
  /// // returns false, Leading zeros must be excluded
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.excluded);
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 判断[segments]中的所有元素是否都是有效的IPv4段。
  ///
  /// [leadingZerosMode]用于如何判断前导零,默认值为`null`,此时使用`options.ipv4InputIpLeadingZerosMode`的值。
  /// [checkLength] 是否检查长度, 默认为`true`, 即检查长度。如果为`true`, 则[segments]的长度必须为4。
  ///
  /// 示例
  /// ```dart
  /// // 此时, 使用 options.ipv4InputIpLeadingZerosMode 的值.
  /// isIpv4Segments(["192", "168", "1", "1"]);
  /// // 返回 true
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.any);
  /// // 返回 false, 必须包含前导零,
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.included);
  /// // 返回 false, 必须包含完整的前导零
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 true, 必须不能包含前导零
  /// isIpv4Segments(["192", "168", "1", "1"], inputMode: LeadingZerosMode.excluded);
  ///
  /// // 此时, 使用 options.ipv4InputIpLeadingZerosMode 的值.
  /// isIpv4Segments(["192", "168", "01", "01"]);
  /// // 返回 true
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.any);
  /// // 返回 true, 必须包含前导零
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.included);
  /// // 返回 false, 必须包含完整的前导零, 此例中的 01 不完整
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 false, 必须不能包含前导零
  /// isIpv4Segments(["192", "168", "01", "01"], inputMode: LeadingZerosMode.excluded);
  ///
  /// // 此时, 使用 options.ipv4InputIpLeadingZerosMode 的值.
  /// isIpv4Segments(["192", "168", "001", "001"]);
  /// // 返回 true
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.any);
  /// // 返回 true, 必须包含前导零
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.included);
  /// // 返回 true, 必须包含完整的前导零
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 false, 必须不能包含前导零
  /// isIpv4Segments(["192", "168", "001", "001"], inputMode: LeadingZerosMode.excluded);
  /// ```
  bool isIpv4Segments(Iterable<String> segments,
      {LeadingZerosMode? inputMode, checkLength = true}) {
    if (segments.isEmpty ||
        (checkLength && segments.length != ipv4SegmentCount)) {
      return false;
    }
    return segments.every((part) => isIpv4Segment(part, inputMode: inputMode));
  }

  /// ### English
  /// [isIpv4Segments] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4Segments]的否定形式。
  bool isNotIpv4Segments(Iterable<String> segments,
      {LeadingZerosMode? inputMode, checkLength = true}) {
    return !isIpv4Segments(segments,
        inputMode: inputMode, checkLength: checkLength);
  }

  /// ### English
  /// Check if the given [segment] is a valid IPv4 segment.
  ///
  /// [inputMode] is used to determine how to handle leading zeros in the input.
  ///
  /// Example
  /// ```dart
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segment("019");
  /// // returns true
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.any);
  /// // returns true,Leading zeros must be included
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.included);
  /// // returns true,Leading zeros must be included completely
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.includedCompletely);
  /// // returns false,Leading zeros must be excluded
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.excluded);
  ///
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segment("19");
  /// // returns true
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.any);
  /// // returns false,Leading zeros must be included
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.included);
  /// // returns false,Leading zeros must be included completely
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.includedCompletely);
  /// // returns true,Leading zeros must be excluded
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.excluded);
  ///
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segment("001");
  /// // returns true
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.any);
  /// // returns true,Leading zeros must be included
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.included);
  /// // returns true,Leading zeros must be included completely
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.includedCompletely);
  /// // returns false,Leading zeros must be excluded
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.excluded);
  ///
  /// // In this case, the value of options.ipv4InputIpLeadingZerosMode is used
  /// isIpv4Segment("01");
  /// // returns true
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.any);
  /// // returns true,Leading zeros must be included
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.included);
  /// // returns false,Leading zeros must be included completely
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.includedCompletely);
  /// // returns false,Leading zeros must be excluded
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.excluded);
  /// ```
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[segment]是否是一个有效的IPv4部分。
  ///
  /// [inputMode]用于如何判断前导零,默认值为`null`,此时使用`options.ipv4InputIpLeadingZerosMode`的值。
  ///
  /// 示例
  /// ```dart
  /// // 此时根据 options.ipv4InputIpLeadingZerosMode 的值进行判断
  /// isIpv4Segment("019");
  /// // 返回 true
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.any);
  /// // 返回 true,必须包含前导零
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.included);
  /// // 返回 true,必须包含完整的前导零
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 false,必须不能包含前导零
  /// isIpv4Segment("019", inputMode: LeadingZerosMode.excluded);
  ///
  /// // 此时根据 options.ipv4InputIpLeadingZerosMode 的值进行判断
  /// isIpv4Segment("19");
  /// // 返回 true
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.any);
  /// // 返回 false,必须包含前导零
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.included);
  /// // 返回 false,必须包含完整的前导零
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 true,必须不能包含前导零
  /// isIpv4Segment("19", inputMode: LeadingZerosMode.excluded);
  ///
  /// // 此时根据 options.ipv4InputIpLeadingZerosMode 的值进行判断
  /// isIpv4Segment("001");
  /// // 返回 true
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.any);
  /// // 返回 true,必须包含前导零
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.included);
  /// // 返回 true,必须包含完整的前导零
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 false,必须不能包含前导零
  /// isIpv4Segment("001", inputMode: LeadingZerosMode.excluded);
  ///
  /// // 此时根据 options.ipv4InputIpLeadingZerosMode 的值进行判断
  /// isIpv4Segment("01");
  /// // 返回 true
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.any);
  /// // 返回 true,必须包含前导零
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.included);
  /// // 返回 false,必须包含完整的前导零
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.includedCompletely);
  /// // 返回 false,必须不能包含前导零
  /// isIpv4Segment("01", inputMode: LeadingZerosMode.excluded);
  /// ```
  bool isIpv4Segment(String segment, {LeadingZerosMode? inputMode}) {
    inputMode ??= options.ipv4InputAddressLeadingZerosMode;
    return ipv4SegmentLeadingZerosModeAndRegExpMap[inputMode]!
        .hasMatch(segment);
  }

  /// ### English
  /// [isIpv4Segment] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4Segment]的否定形式。
  bool isNotIpv4Segment(String segment, {LeadingZerosMode? inputMode}) {
    return !isIpv4Segment(segment, inputMode: inputMode);
  }

  /// ### English
  /// Check if the given [ipv4] is a valid IPv4 address.
  ///
  /// Warning: Some tools handle prefix zeros in IP addresses differently.
  /// For example, the command "Ping 192.168.1.010" in Windows treats "010" as octal,
  /// ultimately executing the command "Ping 192.168.1.8".
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[ipv4]是否是一个有效的IPv4地址。
  ///
  /// 警告: 一些工具处理IP地址前缀零的方式不同。
  /// 例如，在Windows中，命令"Ping 192.168.1.010"将"010"视为八进制，最终执行命令"Ping 192.168.1.8"。
  bool isIpv4(String ipv4, {LeadingZerosMode? inputMode}) {
    inputMode ??= options.ipv4InputAddressLeadingZerosMode;
    return ipv4LeadingZerosModeAndRegExpMap[inputMode]!.hasMatch(ipv4);
  }

  /// ### English
  /// [isIpv4] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4]的否定形式。
  bool isNotIpv4(String ipv4, {LeadingZerosMode? inputMode}) {
    return !isIpv4(ipv4, inputMode: inputMode);
  }

  /// ### English
  /// Check if the given [ipv4Int] is a valid IPv4 integer.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[ipv4Int]是否是一个有效的IPv4整数。
  bool isIpv4Int(int ipv4Int) {
    return ipv4Int >= ipv4MinInt && ipv4Int <= ipv4MaxInt;
  }

  /// ### English
  /// [isIpv4Int] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4Int]的否定形式。
  bool isNotIpv4Int(int ipv4Int) {
    return !isIpv4Int(ipv4Int);
  }

  /// ### English
  /// Check if the given [ipv4BigInt] is a valid IPv4 big integer.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[ipv4BigInt]是否是一个有效的IPv4大整数。
  bool isIpv4BigInt(BigInt ipv4BigInt) {
    return ipv4BigInt >= BigInt.from(ipv4MinInt) &&
        ipv4BigInt <= BigInt.from(ipv4MaxInt);
  }

  /// ### English
  /// [ipv4BigInt] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [ipv4BigInt]的否定形式。
  bool isNotIpv4BigInt(BigInt ipv4BigInt) {
    return !isIpv4BigInt(ipv4BigInt);
  }

  /// Check if the given [ipv4WithCidr] is a valid IP v4 address with CIDR mask.
  ///
  /// [inputModeIp] and [inputModeCidr] are optional, and default to
  /// `options.ipv4InputIpLeadingZerosMode` and `options.ipv4InputCidrLeadingZerosMode`
  /// respectively.
  ///
  /// For example, "192.168.1.1/24" is a valid IPv4 address with CIDR mask.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[ipv4WithCidr]是否是一个有效的IPv4地址，并带有CIDR掩码。
  ///
  /// [inputModeIp] 和 [inputModeCidr] 是可选的，默认值为
  ///  `options.ipv4InputIpLeadingZerosMode` and `options.ipv4InputCidrLeadingZerosMode`
  bool isIpv4WithCidr(String ipv4WithCidr,
      {LeadingZerosMode? inputModeIp, LeadingZerosMode? inputModeCidr}) {
    List<String> ipWithCidr = ipv4WithCidr.split('/');
    if (ipWithCidr.length != 2) {
      return false;
    }

    var [ip, cidr] = ipWithCidr;

    return isIpv4(ip, inputMode: inputModeIp) &&
        isIpv4Cidr(cidr, inputMode: inputModeCidr);
  }

  /// ### English
  /// [isIpv4WithCidr] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4WithCidr]的否定形式。
  bool isNotIpv4WithCidr(String ipv4WithCidr,
      {LeadingZerosMode? inputModeIp, LeadingZerosMode? inputModeCidr}) {
    return !isIpv4WithCidr(ipv4WithCidr,
        inputModeIp: inputModeIp, inputModeCidr: inputModeCidr);
  }

  /// ### English
  /// Check if the given [mask] is a valid IPv4 mask.
  ///
  /// [inputMode] are optional, and default to `options.ipv4InputMaskLeadingZerosMode`
  /// respectively.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[mask]是否是一个有效的IPv4掩码。
  ///
  /// [inputMode]是可选的，默认值为`options.ipv4InputMaskLeadingZerosMode`
  bool isIpv4Mask(String mask, {LeadingZerosMode? inputMode}) {
    return isIpv4(mask, inputMode: inputMode) &&
        ipv4MaskCidrMap.containsKey(removeIpv4LeadingZeros(mask));
  }

  /// ### English
  /// [isIpv4Mask] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4Mask]的否定形式。
  bool isNotIpv4Mask(String mask, {LeadingZerosMode? inputMode}) {
    return !isIpv4Mask(mask, inputMode: inputMode);
  }

  /// ### English
  /// Check if the given [cidr] is a valid IPv4 CIDR.
  ///
  /// [inputMode] are optional, and default to `options.ipv4InputCidrLeadingZerosMode`
  /// respectively.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 检查给定的[cidr]是否是一个有效的IPv4 CIDR。
  ///
  /// [inputMode]是可选的，默认值为`options.ipv4InputCidrLeadingZerosMode`
  bool isIpv4Cidr(String cidr, {LeadingZerosMode? inputMode}) {
    inputMode = inputMode ?? options.ipv4InputCidrLeadingZerosMode;
    return ipv4CidrLeadingZerosModeAndRegExpMap[inputMode]!.hasMatch(cidr);
  }

  /// ### English
  /// [isIpv4Cidr] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4Cidr]的否定形式。
  bool isNotIpv4Cidr(String cidr, {LeadingZerosMode? inputMode}) {
    return !isIpv4Cidr(cidr, inputMode: inputMode);
  }

  /// ### English
  /// Check if the given [cidr] is a valid IPv4 CIDR integer.
  ///
  /// ---
  /// ### 中文(Chinese)
  /// 检查给定的[cidr]是否是一个有效的IPv4 CIDR整数。
  bool isIpv4CidrInt(int cidr) {
    return cidr >= ipv4CidrMin && cidr <= ipv4CidrMax;
  }

  /// ### English
  /// [isIpv4CidrInt] negation form.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// [isIpv4CidrInt]的否定形式。
  bool isNotIpv4CidrInt(int cidr) {
    return !isIpv4CidrInt(cidr);
  }

  /// ### English
  /// Create list of segments in the given IPv4 [ipv4].
  ///
  /// Same as [ipv4ToSegmentsDefault()], but throws an [IpError] exception
  /// when encountering an invalid IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将IPv4地址转换为列表。
  ///
  /// 与[ipv4ToSegmentsDefault()]方法类似, 但当遇到非法IPv4地址时会抛出[IpError]异常。
  List<String> ipv4ToSegments(String ipv4, {LeadingZerosMode? inputMode}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      return ipv4.split('.');
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  /// ### English
  /// Convert to list of segments in the given IPv4 [ipv4].
  ///
  /// If [ipv4] is not a valid IPv4 address, return [defaultValue].
  ///
  /// For example,
  /// - ipv4ToSegmentsDefault("192.168.1.1", inputMode: LeadingZerosMode.any); // returns ["192", "168", "1", "1"]
  /// - ipv4ToSegmentsDefault("192.168.1."); // returns null
  /// - ipv4ToSegmentsDefault("192.168.1.", defaultValue: ["default"]); // returns ["default"]
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将IPv4地址转换为列表。
  ///
  /// 如果[ipv4]不是有效的IPv4地址, 返回[defaultValue]。
  /// 如果[inputMode]没有指定, 则使用`options.ipv4InputIpLeadingZerosMode`。
  ///
  /// 示例
  /// - ipv4ToSegmentsDefault("192.168.1.1", inputMode: LeadingZerosMode.any); // 返回 ["192", "168", "1", "1"]
  /// - ipv4ToSegmentsDefault("192.168.1.") 返回 null.
  /// - ipv4ToSegmentsDefault("192.168.1.", defaultValue: ["default"]) 返回 ["default"].
  List<String>? ipv4ToSegmentsDefault(String ipv4,
      {List<String>? defaultValue, LeadingZerosMode? inputMode}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      return ipv4.split('.');
    }
    return defaultValue;
  }

  /// ### English
  /// To Uint8List of segments in the given IPv4 [ipv4]. Uint8List is unmodifiable.
  ///
  /// Same as [ipv4ToInt8SegmentsDefault()], but throws an [IpError] exception
  /// when encountering an invalid IPv4 address.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将IPv4地址转换为Uint8List。
  ///
  /// 与[ipv4ToInt8SegmentsDefault()]方法类似, 但当遇到非法IPv4地址时会抛出[IpError]异常。
  Uint8List ipv4ToInt8Segments(String ipv4, {LeadingZerosMode? inputMode}) {
    Uint8List? parts = ipv4ToInt8SegmentsDefault(ipv4, inputMode: inputMode);
    if (parts != null) {
      return parts;
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  /// ### English
  /// Convert to Uint8List of segments in the given IPv4 [ipv4].
  ///
  /// If [ipv4] is not a valid IPv4 address, return [defaultValue].
  /// If [inputMode] is not specified, it will use `options.ipv4InputIpLeadingZerosMode`
  ///
  /// For example,
  /// - ipv4ToInt8SegmentsDefault("192.168.1.1", inputMode: LeadingZerosMode.any); // returns [192, 168, 1, 1].
  /// - ipv4ToInt8SegmentsDefault("192.168.1.") returns null.
  /// - ipv4ToInt8SegmentsDefault("192.168.1.", defaultValue: [0,0,0,0]) returns [0,0,0,0].
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 将IPv4地址转换为Uint8List。
  ///
  /// 如果[ipv4]不是有效的IPv4地址, 返回[defaultValue]。
  /// 如果[inputMode]没有指定, 则使用`options.ipv4InputIpLeadingZerosMode`。
  ///
  /// 示例
  /// - ipv4ToInt8SegmentsDefault("192.168.1.1", inputMode: LeadingZerosMode.any); // 返回 [192, 168, 1, 1].
  /// - ipv4ToInt8SegmentsDefault("192.168.1.") 返回 null.
  /// - ipv4ToInt8SegmentsDefault("192.168.1.", defaultValue: [0,0,0,0]) 返回 [0,0,0,0].
  Uint8List? ipv4ToInt8SegmentsDefault(String ipv4,
      {Uint8List? defaultValue, LeadingZerosMode? inputMode}) {
    List<String>? parts = ipv4ToSegmentsDefault(ipv4, inputMode: inputMode);
    if (parts != null) {
      return Uint8List.fromList(parts.map(int.parse).toList());
    }
    return defaultValue;
  }

  /// ### English
  /// Convert to subnet mask from [cidr].
  ///
  /// Same as [ipv4CidrToMaskDefault()], but throws an [IpError] exception
  /// when encountering an invalid IPv4 CIDR  .
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 从[cidr]字符串获取IPv4子网掩码。
  ///
  /// 与[ipv4CidrToMaskDefault()]方法类似, 但当遇到非法IPv4 CIDR时会抛出[IpError]异常。
  String ipv4CidrToMask(String cidr,
      {LeadingZerosMode? inputMode, LeadingZerosMode? outputMode}) {
    String? mask = ipv4CidrToMaskDefault(cidr,
        inputMode: inputMode, outputMode: outputMode);
    if (mask != null) {
      return mask;
    }
    throw CidrError('Invalid IPv4 CIDR: $cidr, IPv4 CIDR should be between '
        '$ipv4CidrMin and $ipv4CidrMax .');
  }

  /// ### English
  /// Convert to IPv4 subnet mask from [cidr] string.
  ///
  /// If [cidr] is not a valid IPv4 CIDR, returns [defaultValue].
  ///
  /// Example
  /// - ipv4CidrToMaskDefault("24") returns "255.255.255.0"
  /// - ipv4CidrToMaskDefault("33", defaultValue: "no mask") returns "no mask"
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 从[cidr]字符串获取IPv4子网掩码。
  ///
  /// 如果[cidr]不是有效的IPv4 CIDR, 返回[defaultValue]。
  ///
  /// 示例
  /// - ipv4CidrToMaskDefault("24") 返回 "255.255.255.0"
  /// - ipv4CidrToMaskDefault("33", defaultValue: "no mask") 返回 "no mask"
  String? ipv4CidrToMaskDefault(String cidr,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      LeadingZerosMode? outputMode}) {
    if (isIpv4Cidr(cidr, inputMode: inputMode)) {
      return ipv4CidrIntToMaskDefault(int.parse(cidr),
          defaultValue: defaultValue, outputMode: outputMode);
    }
    return defaultValue;
  }

  /// ### English
  /// Convert to IPv4 subnet mask from [cidr].
  ///
  /// This method is similar to [ipv4CidrIntToMaskDefault],
  /// but the difference is that this method throws a [CidrError] exception
  /// when encountering an invalid IPv4 CIDR.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 获取IPv4子网掩码从[cidr]。
  ///
  /// 此方法与[ipv4CidrIntToMaskDefault]方法类似, 的区别在于此方法在遇到非法IPv4 CIDR时会抛出[CidrError]异常,
  String ipv4CidrIntToMask(int cidr, {LeadingZerosMode? outputMode}) {
    String? mask = ipv4CidrIntToMaskDefault(cidr, outputMode: outputMode);
    if (mask != null) {
      return mask;
    }
    throw CidrError('Invalid IPv4 CIDR: $cidr, IPv4 CIDR should be between '
        '$ipv4CidrMin and $ipv4CidrMax.');
  }

  /// ### English
  /// Convert to IPv4 subnet mask from [cidr].
  ///
  /// If [cidr] is not an integer between 0 and 32, returns [defaultValue].
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 获取IPv4子网掩码从[cidr]。
  ///
  /// 如果[cidr]不是0到32之间的整数, 返回[defaultValue]。
  String? ipv4CidrIntToMaskDefault(int cidr,
      {String? defaultValue, LeadingZerosMode? outputMode}) {
    if (isIpv4CidrInt(cidr)) {
      String mask = ipv4MaskCidrMap.entries
          .firstWhere((entry) => entry.value == cidr)
          .key;
      return handleIpv4Output(mask,
          inputMode: LeadingZerosMode.any, outputMode: outputMode);
    }
    return defaultValue;
  }

  /// ### English
  /// Convert to IPv4 CIDR from [mask].
  ///
  /// This method is similar to [ipv4MaskToCidrDefault],
  /// but the difference is that this method throws a [MaskError] exception
  /// when encountering an invalid IPv4 mask.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 获取IPv4 CIDR从[mask]。
  ///
  /// 此方法与[ipv4MaskToCidrDefault]方法类似, 区别在于此方法在遇到非法IPv4掩码时会抛出[MaskError]异常,
  int ipv4MaskToCidr(String mask, {LeadingZerosMode? inputMode}) {
    int? cidr = ipv4MaskToCidrDefault(mask, inputMode: inputMode);
    if (cidr != null) {
      return cidr;
    }
    throw MaskError('Invalid IPv4 mask: $mask');
  }

  /// ### English
  /// Convert to IPv4 CIDR from [mask].
  ///
  /// If [mask] is not a valid IPv4 mask, returns [defaultValue].
  ///
  /// Examples,
  /// - ipv4MaskToCidrDefault("255.255.255.0") returns 24
  /// - ipv4MaskToCidrDefault("255.255.255.256") returns null
  /// - ipv4MaskToCidrDefault("255.255.255.256", defaultValue: 0) returns 0
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 获取IPv4 CIDR从[mask]。
  ///
  /// 如果[mask]不是有效的IPv4掩码，返回[defaultValue]。
  ///
  /// 示例
  /// - ipv4MaskToCidrDefault("255.255.255.0") 返回 24
  /// - ipv4MaskToCidrDefault("255.255.255.256") 返回 null
  /// - ipv4MaskToCidrDefault("255.255.255.256", defaultValue: 0) 返回 0
  int? ipv4MaskToCidrDefault(String mask,
      {int? defaultValue, LeadingZerosMode? inputMode}) {
    if (isIpv4Mask(mask, inputMode: inputMode)) {
      return ipv4MaskCidrMap[mask] ?? defaultValue;
    }
    return defaultValue;
  }

  /// ### English
  /// Remove leading zeros in IPv4 addresses.
  ///
  /// This method is similar to [removeIpv4LeadingZerosDefault],
  /// but the difference is that this method throws a [IpError] exception
  /// when encountering an invalid IPv4 address,
  /// while [removeIpv4LeadingZerosDefault] returns defaultValue.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 移除IPv4地址中的前导零。
  ///
  /// 此方法与[removeIpv4LeadingZerosDefault]方法类似, 区别在于此方法在遇到非法IPv4地址时会抛出[IpError]异常,
  /// 而[removeIpv4LeadingZerosDefault]方法在遇到非法IPv4地址时会返回defaultValue。
  String removeIpv4LeadingZeros(String ipv4,
      {LeadingZerosMode inputMode = LeadingZerosMode.any}) {
    String? ipv4WithoutLeadingZeros =
        removeIpv4LeadingZerosDefault(ipv4, inputMode: inputMode);
    if (ipv4WithoutLeadingZeros != null) {
      return ipv4WithoutLeadingZeros;
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  /// English
  /// Remove leading zeros in IPv4 addresses.
  ///
  /// If [ipv4] is not a valid IPv4 address, return [defaultValue].
  /// [inputMode] are optional, and default is `LeadingZerosMode.any`,
  /// ** NOT ** `options.ipv4InputIpLeadingZerosMode`
  ///
  /// For example,
  /// - removeIpv4LeadingZerosDefault("192.168.1.1") returns "192.168.1.1"
  /// - removeIpv4LeadingZerosDefault("192.168.01.1") returns "192.168.1.1"
  /// - removeIpv4LeadingZerosDefault("192.168.1.256") returns null
  /// - removeIpv4LeadingZerosDefault("192.168.1.256", defaultValue: "bad ip") returns "bad ip"
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 移除IPv4地址中的前导零。
  ///
  /// 如果[ipv4]不是有效的IPv4地址，返回[defaultValue]。
  /// [inputMode]是可选的，默认值是`LeadingZerosMode.any`，
  /// **不是** `options.ipv4InputIpLeadingZerosMode`
  ///
  /// 示例
  /// - removeIpv4LeadingZerosDefault("192.168.1.1") 返回 "192.168.1.1"
  /// - removeIpv4LeadingZerosDefault("192.168.01.1") 返回 "192.168.1.1"
  /// - removeIpv4LeadingZerosDefault("192.168.1.256") 返回 null
  /// - removeIpv4LeadingZerosDefault("192.168.1.256", defaultValue: "bad ip") 返回 "bad ip"
  String? removeIpv4LeadingZerosDefault(String ipv4,
      {String? defaultValue,
      LeadingZerosMode inputMode = LeadingZerosMode.any}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      return ipv4.split('.').map((part) => '${int.parse(part)}').join('.');
    }
    return defaultValue;
  }

  /// ### English
  /// Add leading zeros to IPv4 addresses.
  ///
  /// This method is similar to [addIpv4LeadingZerosDefault],
  /// but the difference is that this method throws a [IpError] exception
  /// when encountering an invalid IPv4 address,
  /// while [addIpv4LeadingZerosDefault] returns defaultValue.
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 增加IPv4地址中的前导零。
  ///
  /// 此方法与[addIpv4LeadingZerosDefault]方法类似, 的区别在于此方法在遇到非法IPv4地址时会抛出[IpError]异常,
  /// 而[addIpv4LeadingZerosDefault]方法在遇到非法IPv4地址时会返回defaultValue。
  String addIpv4LeadingZeros(String ipv4,
      {LeadingZerosMode inputMode = LeadingZerosMode.any,
      bool incompleteLeadingZeros = false}) {
    String? ipv4WithLeadingZeros = addIpv4LeadingZerosDefault(ipv4,
        inputMode: inputMode, incompleteLeadingZeros: incompleteLeadingZeros);
    if (ipv4WithLeadingZeros != null) {
      return ipv4WithLeadingZeros;
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  /// ### English
  /// Add leading zeros to IPv4 addresses.
  ///
  /// If [ipv4] is not a valid IPv4 address, returns [defaultValue].
  /// [inputMode] is optional, and default is `LeadingZerosMode.any`,
  /// ** NOT ** [options.ipv4InputIpLeadingZerosMode]
  ///
  /// [incompleteLeadingZeros] is optional, and default is false.
  /// Used to determine whether to add an incomplete leading zero to an IPv4 address.
  /// This parameter may not be used in practice, and is only used to generate test data in tests.
  ///
  /// For example,
  /// - addIpv4LeadingZerosDefault("192.168.1.1") returns "192.168.001.001"
  /// - addIpv4LeadingZerosDefault("192.168.1.1",incompleteLeadingZeros: true) returns "192.168.01.01"
  /// - addIpv4LeadingZerosDefault("192.168.1.256") returns null
  /// - addIpv4LeadingZerosDefault("192.168.1.256", defaultValue: "bad ip") returns "bad ip"
  ///
  /// ---
  ///
  /// ### 中文(Chinese)
  /// 增加IPv4地址中的前导零。
  ///
  /// 如果[ipv4]不是有效的IPv4地址，返回[defaultValue]。
  /// [inputMode]是可选的，默认值是`LeadingZerosMode.any`，
  /// **不是** `options.ipv4InputIpLeadingZerosMode`
  ///
  /// [incompleteLeadingZeros]是可选的，默认值是false。
  /// 用于判断是否添加IPv4地址中的不完整前导零。此参数在实际中可能用不到, 这里仅用于在测试中生成测试数据。
  ///
  /// 示例
  /// - addIpv4LeadingZerosDefault("192.168.1.1") 返回 "192.168.001.001"
  /// - addIpv4LeadingZerosDefault("192.168.1.1",incompleteLeadingZeros: true) 返回 "192.168.01.01"
  /// - addIpv4LeadingZerosDefault("192.168.1.256") 返回 null
  /// - addIpv4LeadingZerosDefault("192.168.1.256", defaultValue: "bad ip") 返回 "bad ip"
  String? addIpv4LeadingZerosDefault(String ipv4,
      {String? defaultValue,
      LeadingZerosMode inputMode = LeadingZerosMode.any,
      bool incompleteLeadingZeros = false}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      if (incompleteLeadingZeros) {
        return ipv4
            .split('.')
            .map((part) => part.length == 1 ? '0$part' : part.padLeft(3, '0'))
            .join('.');
      }
      return ipv4.split('.').map((part) => part.padLeft(3, '0')).join('.');
    }
    return defaultValue;
  }

  // ==========================================================================
  // ====================== IPv6 functions ====================================
  // ==========================================================================
  List<String> createIpv6ListFromRanges(String ipRanges,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode,
      bool? outputCompressed}) {
    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;

    handleRange(
        String startIp, String endIp, String ipRange, List<String> ipList) {
      if (isNotIpv6(startIp,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
        throw IpRangeError('Invalid start IP: $startIp in range $ipRange');
      }

      if (isIpv4MappedIpv6(startIp,
          inputMode: inputMode, inputCaseMode: inputCaseMode)) {
        List<String> startIpParts = startIp.split(':ffff:');
        String startIpv4 = startIpParts[1];
        String endIpv4 = endIp;
        if (endIp.contains(':ffff:')) {
          endIpv4 = endIp.split(':ffff:')[1];
          List<String> endIpv4Parts = endIpv4.split('.');
          if (endIpv4Parts.length != 4) {
            throw IpRangeError('Invalid end IP: $endIp in range $ipRange');
          }
        }
        Iterable<String> list = createIpv4ListFromRanges('$startIpv4-$endIpv4')
            .map((ipv4) => '${startIpParts[0]}:ffff:$ipv4');
        ipList.addAll(list);
        return;
      }

      String startIpv6 = startIp;
      List<String> startIpParts = startIp.split(':');
      String endIpv6 = endIp;
      if (isNotIpv6(endIp,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
        if (endIp.contains('::')) {
          throw IpRangeError('Invalid end IP: $endIp in range $ipRange');
        }
        List<String> endIpParts = endIp.split(':');
        if (endIpParts.every((part) => _regExpMatch(
            part, ipv6SegmentLeadingZerosModeAndRegExpMap,
            inputMode: inputMode, inputCaseMode: inputCaseMode))) {
          int startIpPartsLength = startIpParts.length;
          int endIpPartsLength = endIpParts.length;
          // completion to [endIp] if it is a partial IP address
          for (int i = 0; i < startIpPartsLength - endIpPartsLength; i++) {
            endIpParts.insert(i, startIpParts[i]);
          }
          endIpv6 = endIpParts.join(':');
        } else {
          throw IpRangeError('Invalid end IP: $endIp in range $ipRange');
        }
      }
      BigInt startInt = ipv6ToBigInt(startIpv6);
      BigInt endInt = ipv6ToBigInt(endIpv6);
      if (startInt > endInt) {
        throw IpRangeError(
            'Invalid IP range: $ipRange, start IP is greater than end IP');
      }
      for (BigInt i = startInt; i <= endInt; i = i + BigInt.one) {
        ipList.add(bigIntToIpv6(i));
      }
    }

    return _createIpListFromRanges(ipRanges, handleRange);
  }

  // ----     IPv4-mapped IPv6 functions     ----

  /// Convert IPv4-mapped IPv6 address to IPv4 address.
  ///
  /// If [ipv4MappedIpv6] is not a valid IPv4-mapped IPv6 address, throws an [IpError].
  String ipv4MappedIpv6ToIpv4(String ipv4MappedIpv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      LeadingZerosMode? outputModeIpv4}) {
    if (isIpv4MappedIpv6(ipv4MappedIpv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      String ipv4 = ipv4MappedIpv6.split(RegExp(':[Ff]{4}:')).last;
      return handleIpv4Output(ipv4,
          inputMode: LeadingZerosMode.any, outputMode: outputModeIpv4);
    }
    throw IpError('Invalid IPv4-mapped IPv6 address: $ipv4MappedIpv6');
  }

  /// Convert IPv4-mapped IPv6 address to IPv4 address.
  ///
  /// If [ipv4MappedIpv6] is not a valid IPv4-mapped IPv6 address, return [defaultValue].
  String? ipv4MappedIpv6ToIpv4Default(String ipv4MappedIpv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      LeadingZerosMode? outputModeIpv4}) {
    try {
      return ipv4MappedIpv6ToIpv4(ipv4MappedIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          outputModeIpv4: outputModeIpv4);
    } on IpUtilError {
      return defaultValue;
    }
  }

  String ipv4ToIpv4MappedIpv6(String ipv4,
      {LeadingZerosMode? inputMode,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode,
      bool? outputCompressed}) {
    final ipv4MappedIpv6 = ipv4ToIpv4MappedIpv6Default(ipv4,
        inputMode: inputMode,
        outputMode: outputMode,
        outputCaseMode: outputCaseMode,
        outputCompressed: outputCompressed);
    if (ipv4MappedIpv6 != null) {
      return ipv4MappedIpv6;
    }
    throw IpError('Invalid IPv4 address: $ipv4');
  }

  String? ipv4ToIpv4MappedIpv6Default(String ipv4,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode,
      bool? outputCompressed}) {
    if (isIpv4(ipv4, inputMode: inputMode)) {
      return _handleIpv4MappedIpv6Output(
          '::ffff:$ipv4', outputCompressed, outputMode, outputCaseMode);
    }
    return defaultValue;
  }

  String bigIntToIpv4MappedIpv6(BigInt ipv4BigInt,
      {bool? outputCompressed,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    if (isIpv4BigInt(ipv4BigInt)) {
      String ipv4Address = bigIntToIpv4(ipv4BigInt, outputMode: outputMode);
      outputCompressed ??= options.ipv6OutputCompressed;
      return _handleIpv4MappedIpv6Output(
          ipv4Address, outputCompressed, outputMode, outputCaseMode);
    }
    throw IpRangeError(
        'The provided value is out of range for an IPv4-mapped IPv6 address.');
  }

  String? bigIntToIpv4MappedIpv6Default(BigInt ipv4BigInt,
      {String? defaultValue,
      bool? outputCompressed,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return bigIntToIpv4MappedIpv6(ipv4BigInt,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode,
          outputCompressed: outputCompressed);
    } on IpUtilError {
      return defaultValue;
    }
  }

  /// Check if the given [ip] is a valid IPv4-mapped IPv6 full address.
  ///
  /// IPv4-mapped IPv6 full address is a full IPv6 address with the prefix
  /// 0:0:0:0:0:0:ffff: followed by a valid IPv4 address.
  ///
  /// Valid examples:
  /// - 0:0:0:0:0:ffff:192.168.1.1
  /// - 00:00:00:000:0000:ffff:192.168.1.1
  ///
  /// [RFC4291 section-2.5.5.2 IPv4-Mapped IPv6 Address](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2)
  ///
  /// ``` plaintext
  /// |                80 bits               | 16 |      32 bits        |
  /// +--------------------------------------+--------------------------+
  /// |0000..............................0000|FFFF|    IPv4 address     |
  /// +--------------------------------------+----+---------------------+
  /// ```
  bool isIpv4MappedIpv6Normal(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return _regExpMatch(ipv6, ipv4MappedIpv6NormalLeadingZerosModeAndRegExpMap,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  bool isNotIpv4MappedIpv6Normal(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return !isIpv4MappedIpv6Normal(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  bool isIpv4MappedIpv6Compressed(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return _regExpMatch(
        ipv6, ipv4MappedIpv6CompressedLeadingZerosModeAndRegExpMap,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  bool isNotIpv4MappedIpv6Compressed(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return !isIpv4MappedIpv6Compressed(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  bool isIpv4MappedIpv6(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return isIpv4MappedIpv6Compressed(ipv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode) ||
        isIpv4MappedIpv6Normal(ipv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  bool isNotIpv4MappedIpv6(String ipv6,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    return !isIpv4MappedIpv6(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
  }

  // ----     IPv6 functions     ----

  BigInt ipv6ToBigInt(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    inputMode ??= options.ipv6InputAddressLeadingZerosMode;
    inputCaseMode ??= options.ipv6InputCaseMode;
    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;

    if (!isIpv6(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      throw IpError('Invalid IPv6 address: $ipv6');
    }

    if (inputIpv4MappedIpv6IsIpv6 &&
        isIpv4MappedIpv6(ipv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      String ipv4 = ipv4MappedIpv6ToIpv4(ipv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          outputModeIpv4: LeadingZerosMode.any);
      return BigInt.from(ipv4ToInt(ipv4, inputMode: inputMode));
    }

    final bytes =
        InternetAddress(ipv6, type: InternetAddressType.IPv6).rawAddress;
    BigInt result = BigInt.zero;
    for (int byte in bytes) {
      result = (result << 8) + BigInt.from(byte);
    }

    return result;
//     ipv6 = toIpv6Normal(ipv6,
//         inputMode: inputMode,
//         inputCaseMode: inputCaseMode,
//         inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
//         outputMode: LeadingZerosMode.includedCompletely);
//
//     List<String> parts = ipv6.split(':');
//
//     BigInt result = BigInt.zero;
//     // for (int i = 0; i < parts.length; i++) {
//     //   result += (BigInt.parse(parts[i], radix: 16) << (16 * (parts.length - i - 1)));
//     // }
// for(var part in parts){
//   result = (result << 16) + BigInt.parse(part, radix: 16);
// }
//     return result;
  }

  BigInt? ipv6ToBigIntDefault(String ipv6,
      {BigInt? defaultValue,
      LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    try {
      return ipv6ToBigInt(ipv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6);
    } on IpUtilError {
      return defaultValue;
    }
  }

  String bigIntToIpv6(BigInt bigIntValue,
      {isIpv4MappedIpv6 = false,
      bool? outputCompressed,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    if (!isIpv6BigInt(bigIntValue)) {
      throw IpRangeError(
          'The provided value is out of range for an IPv6 address.');
    }
    if (isIpv4MappedIpv6) {
      return bigIntToIpv4MappedIpv6(bigIntValue,
          outputCompressed: outputCompressed,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    }
    StringBuffer ipv6Address = StringBuffer();
    for (int i = 7; i >= 0; i--) {
      String groupValue = (bigIntValue >> (i * 16))
          .toUnsigned(16)
          .toRadixString(16)
          .padLeft(4, '0');
      ipv6Address.write(groupValue);
      if (i > 0) {
        ipv6Address.write(':');
      }
    }
    return handleIpv6Output(
      ipv6Address.toString(),
      inputMode: LeadingZerosMode.any,
      inputCaseMode: CaseMode.any,
      outputMode: outputMode,
      outputCaseMode: outputCaseMode,
      outputCompressed: outputCompressed,
    );
  }

  String? bigIntToIpv6Default(BigInt bigIntValue,
      {isIpv4MappedIpv6 = false,
      String? defaultValue,
      bool? outputCompressed,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return bigIntToIpv6(bigIntValue,
          isIpv4MappedIpv6: isIpv4MappedIpv6,
          outputCompressed: outputCompressed,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  bool isIpv6BigInt(BigInt ipv6BigInt) {
    return ipv6BigInt >= ipv6MinBigInt && ipv6BigInt <= ipv6MaxBigInt;
  }

  bool isNotIpv6BigInt(BigInt ipv6BigInt) {
    return !isIpv6BigInt(ipv6BigInt);
  }

  bool isIpv6Normal(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    if (ipv6.contains('::')) {
      return false;
    }
    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;

    bool val = _regExpMatch(ipv6, ipv6NormalLeadingZerosModeAndRegExpMap,
        inputMode: inputMode, inputCaseMode: inputCaseMode);
    return val ||
        (inputIpv4MappedIpv6IsIpv6 &&
            isIpv4MappedIpv6Normal(ipv6,
                inputMode: inputMode, inputCaseMode: inputCaseMode));
  }

  bool isNotIpv6Normal(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    return !isIpv6Normal(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6);
  }

  /// Check if the given [ipv6] is a valid IPv6 compressed address.
  /// Supports prefix zeros.
  ///   - 2001:db8:85a3::8a2e:0370:7334 is a valid IPv6 compressed address.
  ///   - 2001:db8:85a3::8a2e:370:0000 is a valid IPv6 compressed address.
  bool isIpv6Compressed(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    if (!ipv6.contains('::')) {
      return false;
    }
    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;

    if (inputIpv4MappedIpv6IsIpv6 &&
        isIpv4MappedIpv6Compressed(ipv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return true;
    }

    // var parts = ipv6.split('::');
    // if (parts.length != 2) {
    //   return false;
    // }
    try {
      InternetAddress(ipv6, type: InternetAddressType.IPv6);
    } catch (e) {
      return false;
    }

    var ipParts = ipv6.replaceAll('::', ':').split(':');
    return ipParts.every((part) {
      if (part.isEmpty) {
        return true;
      }
      return _regExpMatch(part, ipv6SegmentLeadingZerosModeAndRegExpMap,
          inputMode: inputMode, inputCaseMode: inputCaseMode);
    });

    // for (var part in ipParts) {
    //   bool val = _regExpMatch(part, ipv6SegmentLeadingZerosModeAndRegExpMap,
    //       inputMode: inputMode, inputCaseMode: inputCaseMode);
    //   if (!val) {
    //     return false;
    //   }
    // }
    // return true;
    // var parts = ipv6.split('::');
    // if (parts.length != 2) {
    //   return false;
    // }
    // if (parts[1].startsWith(':')) {
    //   // case :::
    //   return false;
    // }
    // var ipParts = ipv6.replaceAll('::', ':').split(':');
    // if (ipParts.length > 7) {
    //   return false;
    // }
    // // if(ipParts.first.isEmpty && ipParts.last.isEmpty){ // case ::
    // //   return true;
    // // }
    // // if(ipParts.first.isEmpty){ // case ::1
    // //   ipParts.removeAt(0);
    // // }
    // // if(ipParts.last.isEmpty){ // case 1::
    // //   ipParts.removeLast();
    // // }
    // // // case 1::1
    // // var regExp = RegExp(r'^[0-9a-fA-F]{0,4}$');
    // for (var part in ipParts) {
    //   bool val = _regExpMatch(part, ipv6SegmentLeadingZerosModeAndRegExpMap,
    //       inputMode: inputMode, inputCaseMode: inputCaseMode);
    //   if (!val) {
    //     return false;
    //   }
    // }
    // return true;
  }

  bool isNotIpv6Compressed(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    return !isIpv6Compressed(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6);
  }

  /// Check if the given [ipv6] is a valid IPv6 address.
  ///
  /// Supports full and compressed formats.
  /// Supports prefix zeros.
  bool isIpv6(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    return isIpv6Normal(ipv6,
            inputMode: inputMode,
            inputCaseMode: inputCaseMode,
            inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6) ||
        isIpv6Compressed(ipv6,
            inputMode: inputMode,
            inputCaseMode: inputCaseMode,
            inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6);
  }

  bool isNotIpv6(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6}) {
    return !isIpv6(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6);
  }

  List<String> generateRandomIpv6List(BigInt count, bool isIpv4MappedIpv6,
      {LeadingZerosMode outputMode = LeadingZerosMode.any,
      CaseMode outputCaseMode = CaseMode.any,
      bool outputCompressed = false}) {
    var ipv6List = <String>[];
    for (BigInt i = BigInt.zero; i < count; i = i + BigInt.one) {
      ipv6List.add(generateRandomIpv6(isIpv4MappedIpv6,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode,
          outputCompressed: outputCompressed));
    }
    return ipv6List;
  }

  String generateRandomIpv6(bool isIpv4MappedIpv6,
      {LeadingZerosMode outputMode = LeadingZerosMode.any,
      CaseMode outputCaseMode = CaseMode.any,
      bool outputCompressed = false,
      int? zeroCount}) {
    if (isIpv4MappedIpv6) {
      var ipv4 = generateRandomIpv4(outputMode: outputMode);
      return _handleIpv4MappedIpv6Output(
          '::ffff:$ipv4', outputCompressed, outputMode, outputCaseMode);
    }

    final random = Random();
    final ipv6PartList = <String>[];
    for (int i = 0; i < 8; i++) {
      final ipv6Part = random.nextInt(ipv6SegmentMaxInt + 1).toRadixString(16);
      ipv6PartList.add(ipv6Part);
    }
    final ipv6Address = ipv6PartList.join(':');
    return handleIpv6Output(ipv6Address,
        inputMode: LeadingZerosMode.any,
        inputCaseMode: CaseMode.any,
        outputMode: outputMode,
        outputCaseMode: outputCaseMode,
        outputCompressed: outputCompressed);
  }

  /// Convert the given [ipv4OrIpv4MappedIpv6] IPv4 address to IPv4-mapped IPv6 compressed address.
  /// e.g.
  /// - 192.168.1.1 -> ::ffff:192.168.1.1
  /// - ::ffff:192.168.1.1 -> ::ffff:192.168.1.1
  /// - 0:0:0:0:0:ffff:192.168.1.1 -> ::ffff:192.168.1.1
  String toIpv4MappedIpv6Compressed(String ipv4OrIpv4MappedIpv6,
      {LeadingZerosMode? inputMode,
      LeadingZerosMode? inputModeIpv4,
      CaseMode? inputCaseMode,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    inputMode ??= options.ipv6InputAddressLeadingZerosMode;
    inputModeIpv4 ??= options.ipv4InputAddressLeadingZerosMode;
    inputCaseMode ??= options.ipv6InputCaseMode;
    outputMode ??= options.ipv6OutputAddressLeadingZerosMode;
    outputCaseMode ??= options.ipv6OutputCaseMode;

    if (isIpv4(ipv4OrIpv4MappedIpv6, inputMode: inputModeIpv4)) {
      return _handleIpv4MappedIpv6Output(
          '::ffff:$ipv4OrIpv4MappedIpv6', true, outputMode, outputCaseMode);
    }
    if (isIpv4MappedIpv6(ipv4OrIpv4MappedIpv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv4OrIpv4MappedIpv6, true, outputMode, outputCaseMode);
    }

    throw IpUtilError(
        'Can not convert to IPv4-mapped IPv6 compressed address for: $ipv4OrIpv4MappedIpv6');
  }

  String? toIpv4MappedIpv6CompressedDefault(String ipv4OrIpv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return toIpv4MappedIpv6Compressed(ipv4OrIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  /// Convert the given [ipv4OrIpv6] IPv4 address to IPv4-mapped IPv6 full address.
  /// e.g.
  /// - 192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  /// - 0:0:0:0:0:ffff:192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  /// - ::ffff:192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  String toIpv4MappedIpv6Normal(String ipv4OrIpv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      LeadingZerosMode? inputModeIpv4,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    if (isIpv4(ipv4OrIpv6, inputMode: inputModeIpv4)) {
      return _handleIpv4MappedIpv6Output(
          '::ffff:$ipv4OrIpv6', false, outputMode, outputCaseMode);
    }
    if (isIpv4MappedIpv6(ipv4OrIpv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv4OrIpv6, false, outputMode, outputCaseMode);
    }

    throw IpError(
        'Can not convert to IPv4-mapped IPv6 full address: $ipv4OrIpv6');
  }

  String? toIpv4MappedIpv6NormalDefault(String ipv4OrIpv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      LeadingZerosMode? inputModeIpv4,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return toIpv4MappedIpv6Normal(ipv4OrIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputModeIpv4: inputModeIpv4,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  /// Convert the given [ipv4OrIpv6] IP address to IPv6 compressed format.
  /// e.g.
  /// - 192.168.1.1 -> ::ffff:192.168.1.1
  /// - ::ffff:192.168.1.1 -> ::ffff:192.168.1.1
  /// - 0:0:0:0:0:ffff:192.168.1.1 -> ::ffff:192.168.1.1
  /// - 2001:db8::1 -> 2001:db8::1
  /// - 2001:db8::0:1 -> 2001:db8::1    compress again
  /// - 2001:db8::1:0:0:0 -> 2001:db8:0:0:1::    compress again
  /// - 2001:db8:0:0:0:0:2:1 -> 2001:db8::2:1
  /// - 0:0:0:0:0:0:0:1 -> ::1
  /// - 2001:0db8:85a3:0000:0000:8a2e:0370:7334 -> 2001:0db8::8a2e:0370:7334
  String toIpv6Compressed(String ipv4OrIpv6,
      {LeadingZerosMode? inputMode,
      LeadingZerosMode? inputModeIpv4,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    if (isNotIpv6(ipv4OrIpv6,
            inputMode: inputMode,
            inputCaseMode: inputCaseMode,
            inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6) &&
        isNotIpv4(ipv4OrIpv6, inputMode: inputModeIpv4)) {
      throw IpError('Invalid IP address: $ipv4OrIpv6');
    }

    if (isIpv4MappedIpv6(ipv4OrIpv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode) ||
        isIpv4(ipv4OrIpv6, inputMode: inputModeIpv4)) {
      return toIpv4MappedIpv6Compressed(ipv4OrIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    }
    if (isIpv6Compressed(ipv4OrIpv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      ipv4OrIpv6 = toIpv6Normal(ipv4OrIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputModeIpv4: inputModeIpv4,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    }

    // 将 IPv6 地址分割成块
    List<String> blocks = ipv4OrIpv6.split(':');

    // 找到最长的连续零块
    int maxZeroCount = 0;
    int maxZeroStart = -1;
    int currentZeroCount = 0;
    int currentZeroStart = -1;

    for (int i = 0; i < blocks.length; i++) {
      if (blocks[i] == '0' ||
          blocks[i] == '00' ||
          blocks[i] == '000' ||
          blocks[i] == '0000') {
        if (currentZeroStart == -1) {
          currentZeroStart = i;
        }
        currentZeroCount++;
      } else {
        if (currentZeroCount > maxZeroCount) {
          maxZeroCount = currentZeroCount;
          maxZeroStart = currentZeroStart;
        }
        currentZeroCount = 0;
        currentZeroStart = -1;
      }
    }

    // 检查最后一个零块
    if (currentZeroCount > maxZeroCount) {
      maxZeroCount = currentZeroCount;
      maxZeroStart = currentZeroStart;
    }

    // 如果存在连续零块，进行压缩
    if (maxZeroCount > 1) {
      blocks.removeRange(maxZeroStart, maxZeroStart + maxZeroCount);
      blocks.insert(maxZeroStart, '');
    }

    // 将块重新组合成压缩后的地址
    String compressedAddress = blocks.join(':');

    // 处理多个连续零块的情况
    compressedAddress = compressedAddress.replaceAll(':::', '::');

    return _handleIpv6LeadingZerosAndCase(
        compressedAddress, outputMode, outputCaseMode);
    // if (isIpv6Normal(ipv4OrIpv6,
    //     inputMode: inputMode,
    //     inputCaseMode: inputCaseMode,
    //     inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
    //   List<String> parts = ipv4OrIpv6.split(':');
    //
    //   int previousZeroIndex = -1;
    //   List<int> zeroGroup = [];
    //   List<int> currentZeroGroup = [];
    //
    //   for (int i = 0; i < parts.length; i++) {
    //     String part = parts[i];
    //     if (part == '0000' || part == '000' || part == '00' || part == '0') {
    //       currentZeroGroup.add(i);
    //       previousZeroIndex = i;
    //     } else {
    //       if (currentZeroGroup.length > zeroGroup.length) {
    //         zeroGroup = currentZeroGroup.toList(); //copy
    //       }
    //       currentZeroGroup.clear();
    //     }
    //   }
    //
    //   if (currentZeroGroup.length > zeroGroup.length) {
    //     zeroGroup = currentZeroGroup.toList(); //copy
    //   }
    //   if ((zeroGroup.isEmpty && currentZeroGroup.isEmpty) ||
    //       zeroGroup.length == 1) {
    //     return ipv4OrIpv6;
    //   }
    //   if (zeroGroup.length == ipv6MaxSegmentCount) {
    //     return '::';
    //   }
    //
    //   parts[zeroGroup.last] = ':';
    //   if (zeroGroup.length > 2) {
    //     parts.removeRange(zeroGroup.first, zeroGroup.last);
    //   } else if (zeroGroup.length == 2) {
    //     parts.removeAt(zeroGroup.first);
    //   }
    //
    //   return parts.join(':').replaceAll(':::', '::');
    // }
    //
    // if (isIpv6Compressed(ipv4OrIpv6,
    //     inputMode: inputMode, inputCaseMode: inputCaseMode)) {
    //   // Compress again
    //   ipv4OrIpv6 = toIpv6Normal(ipv4OrIpv6,
    //       inputMode: inputMode,
    //       inputCaseMode: inputCaseMode,
    //       inputModeIpv4: inputModeIpv4);
    //   return toIpv6Compressed(ipv4OrIpv6,
    //       inputMode: inputMode,
    //       inputModeIpv4: inputModeIpv4,
    //       inputCaseMode: inputCaseMode,
    //       outputMode: outputMode,
    //       outputCaseMode: outputCaseMode);
    // }
    //
    // throw IpError('Invalid IP address: $ipv4OrIpv6');
  }

  String? toIpv6CompressedDefault(String ipv4OrIpv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      LeadingZerosMode? inputModeIpv4,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return toIpv6Compressed(ipv4OrIpv6,
          inputMode: inputMode,
          inputModeIpv4: inputModeIpv4,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  /// Convert the given [ipv4OrIpv6] IP address to IPv6 normal format.
  /// e.g.
  /// - 192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  /// - ::ffff:192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  /// - 0:0:0:0:0:ffff:192.168.1.1 -> 0:0:0:0:0:ffff:192.168.1.1
  /// - 2001:0db8::8a2e:0370:7334 -> 2001:0db8:0:0:0:8a2e:0370:7334
  /// - 2001:0db8:85a3:0:0:8a2e:0370:7334 -> 2001:0db8:85a3:0:0:8a2e:0370:7334
  /// - :: -> 0:0:0:0:0:0:0:0
  /// - 1:: -> 1:0:0:0:0:0:0:0
  /// - ::1 -> 0:0:0:0:0:0:0:1
  /// - 1::1 -> 1:0:0:0:0:0:0:1
  String toIpv6Normal(String ipv4OrIpv6,
      {LeadingZerosMode? inputMode,
      LeadingZerosMode? inputModeIpv4,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    if (isNotIpv6(ipv4OrIpv6,
            inputMode: inputMode,
            inputCaseMode: inputCaseMode,
            inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6) &&
        isNotIpv4(ipv4OrIpv6, inputMode: inputModeIpv4)) {
      throw IpError('Invalid IP address: $ipv4OrIpv6');
    }

    if (isIpv4MappedIpv6(ipv4OrIpv6,
            inputMode: inputMode, inputCaseMode: inputCaseMode) ||
        isIpv4(ipv4OrIpv6, inputMode: inputModeIpv4)) {
      return toIpv4MappedIpv6Normal(ipv4OrIpv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    }

    if (isIpv6Compressed(ipv4OrIpv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      List<String> parts = ipv4OrIpv6.split('::');
      List<String> left = parts[0].split(':');
      List<String> right = parts[1].split(':');

      List<String> blocks = [];
      blocks.addAll(left);
      while (blocks.length < 8 - right.length) {
        blocks.add('0');
      }
      blocks.addAll(right);

      ipv4OrIpv6 = blocks.join(':');
    }
    return _handleIpv6LeadingZerosAndCase(
        ipv4OrIpv6, outputMode, outputCaseMode);

    // if (isIpv6Compressed(ipv4OrIpv6,
    //     inputMode: inputMode,
    //     inputCaseMode: inputCaseMode,
    //     inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
    //   List<String> parts = ipv4OrIpv6.split('::');
    //   List<String> fullParts = [];
    //   List<String> partLeft = parts[0].split(':');
    //   List<String> partRight = parts[1].split(':');
    //   int leftCount = partLeft.length;
    //   int rightCount = partRight.length;
    //   int fullCount = ipv6MaxSegmentCount - leftCount - rightCount;
    //   if (fullCount < 1) {
    //     throw IpError('Invalid IP address: $ipv4OrIpv6');
    //   }
    //
    //   if (partLeft.length == 1 && partLeft[0] == '') {
    //     partLeft[0] = '0';
    //   }
    //   fullParts.addAll(partLeft);
    //   for (int i = 0; i < fullCount; i++) {
    //     fullParts.add('0');
    //   }
    //   if (partRight.length == 1 && partRight[0] == '') {
    //     partRight[0] = '0';
    //   }
    //   fullParts.addAll(partRight);
    //   return fullParts.join(':');
    // }
    // throw IpError('Invalid IP address: $ipv4OrIpv6');
  }

  String? toIpv6NormalDefault(String ipv4OrIpv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      LeadingZerosMode? inputModeIpv4,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode}) {
    try {
      return toIpv6Normal(ipv4OrIpv6,
          inputMode: inputMode,
          inputModeIpv4: inputModeIpv4,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
          outputMode: outputMode,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  // List<String> toIpv6SegmentList(String ipv6,
  //     {LeadingZerosMode? inputMode,
  //     CaseMode? inputCaseMode,
  //     bool? inputIpv4MappedIpv6IsIpv6}) {
  //   if (isNotIpv6(ipv6,
  //       inputMode: inputMode,
  //       inputCaseMode: inputCaseMode,
  //       inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
  //     throw IpError('Invalid IP address: $ipv6');
  //   }
  //
  //
  //
  // }

  /// Remove leading zeros in IPv6 addresses.
  ///
  /// For example
  /// - 2001:db8::0000:1:2001:0db8 -> 2001:db8::0:1:2001:db8
  /// - ::ffff:192.168.1.01 -> ::ffff:192.168.1.1
  ///
  String removeIpv6LeadingZeros(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      CaseMode? outputCaseMode}) {
    var outputMode = LeadingZerosMode.excluded;
    outputCaseMode ??= options.ipv6OutputCaseMode;

    if (isNotIpv6(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      throw IpError('Invalid IPv6 address: $ipv6');
    }
    if (isIpv4MappedIpv6Compressed(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv6, true, outputMode, outputCaseMode);
    }
    if (isIpv4MappedIpv6Normal(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv6, false, outputMode, outputCaseMode);
    }
    return _handleIpv6LeadingZerosAndCase(ipv6, outputMode, outputCaseMode);
    // return ipv6.split(':').map((f) {
    //   if (f == '0000' || f == '000' || f == '00') {
    //     return '0';
    //   }
    //   if (f.startsWith('000') && f.length == 4) {
    //     return f.replaceFirst('000', '');
    //   }
    //   if (f.startsWith('00') && f.length != 2) {
    //     return f.replaceFirst('00', '');
    //   }
    //   if (f.startsWith('0') && f.length > 1) {
    //     return f.replaceFirst('0', '');
    //   }
    //   return f;
    // }).join(':');
  }

  String? removeIpv6LeadingZerosDefault(String ipv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      CaseMode? inputCaseMode,
      CaseMode? outputCaseMode}) {
    try {
      return removeIpv6LeadingZeros(ipv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
          outputCaseMode: outputCaseMode);
    } on IpUtilError {
      return defaultValue;
    }
  }

  String addIpv6LeadingZeros(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      CaseMode? outputCaseMode,
      bool incompleteLeadingZeros = false}) {
    outputCaseMode ??= options.ipv6OutputCaseMode;

    if (!isIpv6(ipv6,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      throw IpError('Invalid IPv6 address: $ipv6');
    }

    if (isIpv4MappedIpv6Compressed(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv6, true, LeadingZerosMode.any, outputCaseMode);
    }
    if (isIpv4MappedIpv6Normal(ipv6,
        inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return _handleIpv4MappedIpv6Output(
          ipv6, false, LeadingZerosMode.any, outputCaseMode);
    }

    return _handleIpv6LeadingZerosAndCase(
      ipv6,
      incompleteLeadingZeros
          ? LeadingZerosMode.included
          : LeadingZerosMode.includedCompletely,
      outputCaseMode,
    );
  }

  String? addIpv6LeadingZerosDefault(String ipv6,
      {String? defaultValue,
      LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      CaseMode? outputCaseMode,
      bool incompleteLeadingZeros = false}) {
    try {
      return addIpv6LeadingZeros(ipv6,
          inputMode: inputMode,
          inputCaseMode: inputCaseMode,
          inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6,
          outputCaseMode: outputCaseMode,
          incompleteLeadingZeros: incompleteLeadingZeros);
    } on IpUtilError {
      return defaultValue;
    }
  }

  /// Check if the given [ipv6WithCidr] is a valid IP v6 address with CIDR mask.
  ///
  /// IPv6 only supports CIDR mask.
  bool isIpv6WithCidr(String ipv6WithCidr,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? inputModeCidr}) {
    List<String> list = ipv6WithCidr.split('/');
    if (list.length != 2) {
      return false;
    }
    String ip = list[0];
    String cidr = list[1];

    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;

    if (inputIpv4MappedIpv6IsIpv6 &&
        isIpv4MappedIpv6(ip,
            inputMode: inputMode, inputCaseMode: inputCaseMode)) {
      return isIpv4Cidr(cidr, inputMode: inputModeCidr);
    }
    if (isIpv6(ip,
        inputMode: inputMode,
        inputCaseMode: inputCaseMode,
        inputIpv4MappedIpv6IsIpv6: inputIpv4MappedIpv6IsIpv6)) {
      return isIpv6Cidr(cidr, inputMode: inputModeCidr);
    }
    return false;
  }

  bool isIpv6Cidr(String cidr, {LeadingZerosMode? inputMode}) {
    inputMode ??= options.ipv6InputAddressLeadingZerosMode;
    return ipv6CidrLeadingZerosModeAndRegExpMap[inputMode]!.hasMatch(cidr);
  }

  bool isIpv6CidrInt(int cidr) {
    return cidr >= ipv6CidrMin && cidr <= ipv6CidrMax;
  }

  String handleIpv6Output(String ipv6,
      {LeadingZerosMode? inputMode,
      CaseMode? inputCaseMode,
      bool? inputIpv4MappedIpv6IsIpv6,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode,
      bool? outputCompressed}) {
    inputMode ??= options.ipv6InputAddressLeadingZerosMode;
    inputCaseMode ??= options.ipv6InputCaseMode;
    inputIpv4MappedIpv6IsIpv6 ??= options.ipv6InputIpv4MappedIpv6IsIpv6;
    outputMode ??= options.ipv6OutputAddressLeadingZerosMode;
    outputCaseMode ??= options.ipv6OutputCaseMode;
    outputCompressed ??= options.ipv6OutputCompressed;

    if (inputIpv4MappedIpv6IsIpv6) {
      if (isIpv4MappedIpv6(ipv6,
          inputMode: inputMode, inputCaseMode: inputCaseMode)) {
        return _handleIpv4MappedIpv6Output(
            ipv6, outputCompressed, outputMode, outputCaseMode);
      }
    }

    ipv6 = _handleIpv6LeadingZerosAndCase(ipv6, outputMode, outputCaseMode);
    return outputCompressed
        ? toIpv6Compressed(ipv6,
            inputMode: LeadingZerosMode.any,
            inputCaseMode: CaseMode.any,
            outputMode: LeadingZerosMode.any,
            outputCaseMode: CaseMode.any)
        : toIpv6Normal(ipv6,
            inputMode: LeadingZerosMode.any,
            inputCaseMode: CaseMode.any,
            outputMode: LeadingZerosMode.any,
            outputCaseMode: CaseMode.any);
  }

  // ---- IPv6 Private Funtions ----

  bool _regExpMatch(String input, Map<LeadingZerosMode, RegExp> regExpMap,
      {LeadingZerosMode? inputMode, CaseMode? inputCaseMode}) {
    inputCaseMode ??= options.ipv6InputCaseMode;
    if ((inputCaseMode == CaseMode.lowercase && containUppercase(input)) ||
        (inputCaseMode == CaseMode.uppercase && containLowercase(input))) {
      return false;
    }

    inputMode ??= options.ipv6InputAddressLeadingZerosMode;
    RegExp? regExp = regExpMap[inputMode];
    if (regExp == null) {
      throw IpUtilError('Do not contain key: $inputMode in $regExpMap');
    }
    input = input.toLowerCase();
    return regExp.hasMatch(input);
  }

  String _handleIpv4MappedIpv6Output(
      String ipv4MappedIpv6,
      bool? outputCompressed,
      LeadingZerosMode? outputMode,
      CaseMode? outputCaseMode) {
    outputMode ??= options.ipv6OutputAddressLeadingZerosMode;
    outputCaseMode ??= options.ipv6OutputCaseMode;
    outputCompressed ??= options.ipv6OutputCompressed;

    RegExp splitter = RegExp(r':[fF]{4}:');
    var fRegExp = RegExp(r'[fF]{4}');

    var f = '';
    switch (outputCaseMode) {
      case CaseMode.lowercase:
        f = 'ffff';
        break;
      case CaseMode.uppercase:
        f = 'FFFF';
        break;
      case CaseMode.any:
        f = fRegExp.firstMatch(ipv4MappedIpv6)!.group(0)!;
        break;
    }

    var [zeros, ipv4] = ipv4MappedIpv6.split(splitter);
    ipv4 = handleIpv4Output(ipv4, outputMode: outputMode);
    if (outputCompressed) {
      return ':$f$ipv4';
    }
    switch (outputMode) {
      case LeadingZerosMode.included:
        return '000:000:000:000:000:$f:$ipv4';
      case LeadingZerosMode.includedCompletely:
        return '0000:0000:0000:0000:0000:$f:$ipv4';
      case LeadingZerosMode.excluded:
        return '0:0:0:0:0:$f:$ipv4';
      case LeadingZerosMode.any:
        return '$zeros:$f:$ipv4';
    }
  }

  String _handleCase(String input, CaseMode? outputCaseMode) {
    outputCaseMode ??= options.ipv6OutputCaseMode;
    switch (outputCaseMode) {
      case CaseMode.lowercase:
        return input.toLowerCase();
      case CaseMode.uppercase:
        return input.toUpperCase();
      case CaseMode.any:
        return input;
    }
  }

  String _handleIpv6LeadingZerosAndCase(
      String ipv6, LeadingZerosMode? outputMode, CaseMode? outputCaseMode) {
    outputMode ??= options.ipv6OutputAddressLeadingZerosMode;
    ipv6 = _handleCase(ipv6, outputCaseMode);
    switch (outputMode) {
      case LeadingZerosMode.included:
        return ipv6
            .split(':')
            .map((f) => f.isEmpty ? f : f.padLeft(4, '0'))
            .join(':');
      case LeadingZerosMode.includedCompletely:
        return ipv6
            .split(':')
            .map((f) => f.isEmpty ? f : f.padLeft(3, '0'))
            .join(':');
      case LeadingZerosMode.excluded:
        return ipv6.split(':').map((f) {
          if (f == '0000' || f == '000' || f == '00') {
            return '0';
          }
          if (f.startsWith('000') && f.length == 4) {
            return f.replaceFirst('000', '');
          }
          if (f.startsWith('00') && f.length != 2) {
            return f.replaceFirst('00', '');
          }
          if (f.startsWith('0') && f.length > 1) {
            return f.replaceFirst('0', '');
          }
          return f;
        }).join(':');
      case LeadingZerosMode.any:
        return ipv6;
    }
  }

  // === Common functions =====================================================
  // ==========================================================================
  List<String> _createIpListFromRanges(String ipRanges,
      Function(String, String, String, List<String>) handleRange) {
    // Split the ipRanges by comma
    List<String> ipRangeList = ipRanges.trim().split(',');
    List<String> ipList = [];

    // Iterate through each ipRange
    for (String ipRange in ipRangeList) {
      // Split the ipRange by hyphen
      List<String> ipRangeParts = ipRange.split('-');
      if (ipRangeParts.length == 1) {
        String ip = ipRangeParts[0].trim();
        handleRange(ip, ip, ipRange, ipList);
      } else if (ipRangeParts.length == 2) {
        // If the ipRange is a range of IP addresses
        String startIp = ipRangeParts[0].trim();
        String endIp = ipRangeParts[1].trim();
        handleRange(startIp, endIp, ipRange, ipList);
      } else {
        throw IpError('Invalid IP range: $ipRange');
      }
    }
    return ipList;
  }

  /// Check if the given [ip] is a valid IPv4 or IPv6 address.
  ///
  /// Supports full and compressed formats for IPv6.
  bool isIp(String ip) {
    return isIpv4(ip) || isIpv6(ip);
  }

  /// Check if the given [ipWithCidr] is a valid IP address with CIDR mask.
  /// Supports IPv4 and IPv6.
  bool isIpWithCidr(String ipWithCidr) {
    return isIpv4WithCidr(ipWithCidr) || isIpv6WithCidr(ipWithCidr);
  }

  /// Remove leading zeros in the given [ip] IPv4 or IPv6 address.
  String removeIpLeadingZeros(String ip) {
    if (isIpv4(ip)) {
      return removeIpv4LeadingZeros(ip);
    } else if (isIpv6(ip)) {
      return removeIpv6LeadingZeros(ip);
    }

    throw IpError('Invalid IP address: $ip');
  }

  String? tryRemoveIpLeadingZeros(String ip, {String? defaultValue}) {
    try {
      return removeIpLeadingZeros(ip);
    } on IpUtilError {
      return defaultValue;
    }
  }

  String addIpLeadingZeros(String ip) {
    if (isIpv4(ip)) {
      return addIpv4LeadingZeros(ip);
    } else if (isIpv6(ip)) {
      return addIpv6LeadingZeros(ip);
    }

    throw IpError('Invalid IP address: $ip');
  }

  String? tryAddIpLeadingZeros(String ip, {String? defaultValue}) {
    try {
      return addIpLeadingZeros(ip);
    } on IpUtilError {
      return defaultValue;
    }
  }

  String removeStringLeadingZeros(String input) {
    int count = countLeadingZeros(input);
    return input.substring(count);
  }

  bool containLeadingZeros(String str) {
    return str.length > 1 && str.startsWith('0');
  }

  int countLeadingZeros(String str) {
    if (str.isEmpty || str.length == 1) {
      return 0;
    }
    int count = 0;
    int length = str.length - 1;
    for (int i = 0; i < length; i++) {
      if (str[i] == '0') {
        count++;
      } else {
        break;
      }
    }
    return count;
  }

  bool containUppercase(String input) {
    for (int i = 0; i < input.length; i++) {
      int charCode = input.codeUnitAt(i);
      if (charCode >= 65 && charCode <= 90) {
        return true;
      }
    }
    return false;
  }

  bool containLowercase(String input) {
    for (int i = 0; i < input.length; i++) {
      int charCode = input.codeUnitAt(i);
      if (charCode >= 97 && charCode <= 122) {
        return true;
      }
    }
    return false;
  }
}
